条件操作员的不确定行为

undefined behavior in conditional operator

本文关键字:不确定 操作员 条件      更新时间:2023-10-16

我必须分享:

我在以下 Trevial 涉及条件操作员的错误上挂了整整2天。

这是一个简单的更正,但我想知道:

  1. 为什么要编译车载代码?
  2. 错误在做什么?
  3. 为什么很难追踪?

越野车代码:

 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. 错误在做什么?
  3. 为什么很难追踪?

谢谢孩子们。

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)。因此,您正在调用非定位对象上的成员函数。这是不确定的行为。ta-da !!!

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