I had to share this:
I got hung up for 2 full days on the following trivial error involving the Conditional Operator.
It's an easy correction, but I would like to know:
buggy code:
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!!!!
// .....
Clearly, I wrote the Conditional Operator incorrectly. Eveyrthing works totally fine when I finally found and corrected this bug:
correct code:
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!
My program was just hanging when it got near the buggy part - as if it were in an infinite loop. When I ran it with valgrind, I got stuff like
....
==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.
Which was totally unhelpful and pointed me in the wrong director (I thought I was allocating too much on the heap, somehow).
Again,
Thanks kids.
1) The compiler only checks for syntax and a well-formed program. It's up to you to spot the logical bugs.
2) It's undefined behavior. And here's why:
whatever_non_POD_type it_next = condition ? it_next = whatever1 :
it_next = whatever2;
Actually, you can narrow it down to:
It it_next = it_next = whatever;
it doesn't really matter what whatever is. What matters is that until the full statement executes (;
is reached), it_next
is uninitialized. That's what the
It it_next = ...
part attempts to do. But first, it attempts to evaluate what's on the right hand side. Which is it_next = whatever
. Which calls it_next.operator = (whatever)
. So you're calling a member function on an un-initialized object. Which is undefined behavior. Ta-da!!!
3) All undefined behavior is hard to track down. That's why you should at least be aware of common situations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With