Я должен был поделиться этим:
Я завис на 2 полных дня на следующих тривиальный ошибка с условным оператором.
Это простое исправление, но я хотел бы знать:
глючный код:
std::map<int, some_class> my_map;
int key_ctr = 0;
//...
std::map<int, some_class>::iterator it_next =
key_ctr == 0 ?
it_next = my_map.begin() // BUG!!!
:
it_next = --my_map.end(); // BUG!!!!
// .....
Ясно, что я написал Условный оператор неправильно. Eveyrthing прекрасно работает, когда я наконец нашел и исправил эту ошибку:
правильный код:
std::map<int, some_class> my_map;
int key_ctr = 0;
//...
std::map<int, some_class>::iterator it_next =
key_ctr == 0 ?
my_map.begin() // CORRECTED!
:
--my_map.end(); // CORRECTED!
Моя программа просто зависла, когда приблизилась к глючной части — как будто она была в бесконечном цикле. Когда я запустил его с Valgrind, У меня есть такие вещи, как
....
==24570== Warning: set address range perms: large range [0x1a7731000, 0x1c5f79000) (defined)
==24570== Warning: set address range perms: large range [0x1c5f79000, 0x1e47c1000) (defined)
==24570== Warning: set address range perms: large range [0x1e47c1000, 0x203009000) (defined)
==24570== Warning: set address range perms: large range [0x203009000, 0x221851000) (defined)
.....
==3733== More than 10000000 total errors detected. I'm not reporting any more.
Это было совершенно бесполезно и указало мне на неправильного директора (я думал, что я как-то слишком много выделял в куче).
Снова,
Спасибо, дети.
1) Компилятор проверяет только синтаксис и правильно сформированную программу. Это зависит от вас, чтобы определить логические ошибки.
2) Это неопределенное поведение. И вот почему:
whatever_non_POD_type it_next = condition ? it_next = whatever1 :
it_next = whatever2;
На самом деле, вы можете сузить его до:
It it_next = it_next = whatever;
не имеет значения, что бы это ни было. Важно то, что пока не выполнится полный оператор (;
достигнуто), it_next
неинициализирован. Вот что
It it_next = ...
часть попыток сделать. Но во-первых, он пытается оценить, что находится на правой стороне. Который it_next = whatever
, Какие звонки it_next.operator = (whatever)
, Так вы вызываете функцию-член для неинициализированного объекта. Что является неопределенным поведением. Та-да !!!
3) Все неопределенное поведение трудно отследить. Вот почему вы должны хотя бы знать о распространенных ситуациях.
3 Почему было так чертовски сложно выследить?
Потому что у вас не были включены предупреждения компилятора?
$ g++ -std=c++0x -pedantic -Wall -Werror -g m.cc -o m
cc1plus: warnings being treated as errors
m.cc:10: error: operation on ‘it_next’ may be undefined
m.cc: In function ‘void __static_initialization_and_destruction_0(int, int)’:
m.cc:6: error: operation on ‘it_next’ may be undefined
make: *** [m] Error 1