[英]undefined behavior in conditional operator
I had to share this: 我不得不分享这个:
I got hung up for 2 full days on the following trivial error involving the Conditional Operator. 在涉及条件运算符的以下微不足道的错误中,我被挂了2天。
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:
当我最终发现并纠正这个错误时,Eveyrthing工作完全正常:
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
当我用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.
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. 1)编译器只检查语法和格式良好的程序。 It's up to you to spot the logical bugs.
由您来发现逻辑错误。
2) It's undefined behavior. 2)这是未定义的行为。 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 . 重要的是,在完整语句执行(
;
到达)之前, it_next
是未初始化的 。 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
. 这是
it_next = whatever
。 Which calls it_next.operator = (whatever)
. 哪个叫
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. 3)所有未定义的行为很难追踪。 That's why you should at least be aware of common situations.
这就是为什么你至少应该意识到常见的情况。
3 Why it was so damn hard to track down?
3为什么这么难以追踪?
Because you didn't have compiler warnings turned on? 因为您没有打开编译器警告?
$ 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.