简体   繁体   English

条件运算符中的未定义行为

[英]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: 这是一个简单的修正,但我想知道:

  1. Why did the buggy code compile? 为什么错误的代码编译?
  2. What was the bug doing? 这个bug在做什么?
  3. Why it was so damn hard to track down? 为什么这么难以追踪?

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, 再次,

  1. Why did the buggy code compile? 为什么错误的代码编译?
  2. What was the bug doing? 这个bug在做什么?
  3. Why it was so damn hard to track down? 为什么这么难以追踪?

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.

相关问题 是否在由new []运算符分配的内存上调用delete运算符未定义行为? - Is calling delete operator on a memory allocated by new[] operator undefined behavior? 在布尔值上使用按位非运算符(〜)是否会调用未定义的行为? - Does using bitwise not operator (~) on boolean values invoke Undefined Behavior? 在哪些情况下 std::optional operator == 会导致未定义的行为? - In which cases does std::optional operator == cause undefined behavior? 重载运算符删除不删除 object - 有效或未定义的行为? - Overload operator delete to not delete object - valid or undefined behavior? const 成员和赋值运算符。 如何避免未定义的行为? - const member and assignment operator. How to avoid the undefined behavior? 在故障/坏状态未定义行为的istream上调用operator &gt;&gt;吗? - Is calling operator>> on a istream in a fail/bad state undefined behavior? 对未定义的C ++移位操作符行为和包装“模式空间”感到困惑 - Confused by undefined C++ shift operator behavior and wrapping “pattern space” —运算符的行为 - Behavior of — operator 条件运算符中的运算符优先级 - Operator Precedence in Conditional Operator 这是未定义的行为吗? - Is this undefined behavior or not?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM