Undefined behavior in a conditional statement

I had to share this:

I was hanged for 2 full days for the next trivial error related to the Conditional Operator.

This is an easy correction, but I would like to know:

  • Why compilation of error codes?
  • What happened with the error?
  • Why is it so hard to trace?

error 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 statement incorrectly. Eveyrthing works fine when I finally found and fixed this error:

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 just hung when it approached the buggy part - as if it were in an endless 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. 

It was completely useless and pointed to me in the wrong director (I thought I allocated too much heap).

Yet again,

  • Why compilation of error codes?
  • What happened with the error?
  • Why is it so hard to trace?

Thanks to the children.

+4
source share
2 answers

1) The compiler only checks the syntax and well-formed program. It is up to you to identify logical errors.

2) This behavior is undefined. And that'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 whatsoever. The important thing is that until the full operator ( ; ) is it_next , it_next not initialized . This is what

 It it_next = ... 

trying to do. But firstly, he is trying to appreciate that on the right side. This is it_next = whatever . What causes it_next.operator = (whatever) . Therefore, you call a member function on an uninitialized object . This behavior is undefined. TA-dah!!!

3) All undefined behavior is hard to track. That is why you should at least be aware of common situations.

+7
source

3 Why is it so hard to track?

Because you did not have compiler warnings?

 $ g++ -std=c++0x -pedantic -Wall -Werror -g m.cc -om 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 
+7
source

Source: https://habr.com/ru/post/1442176/


All Articles