4

我不得不分享这个:

由于以下涉及条件运算符的琐碎错误,我被挂断了整整 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!!!!

  // .....

显然,我写错了条件运算符。当我终于找到并纠正了这个错误时,一切都很好:

正确的代码:

 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. 为什么追查这么难?

谢谢孩子们。

4

2 回答 2

7

1) 编译器只检查语法和格式良好的程序。找出逻辑错误由您决定。

2)这是未定义的行为。这就是为什么:


whatever_non_POD_type it_next = condition ? it_next = whatever1 : 
                                            it_next  = whatever2; 

实际上,您可以将其缩小为:

It it_next = it_next = whatever;

不管是什么都不重要。重要的是,在完整的语句执行(;到达)之前,it_next 它是 uninitialized。这就是

It it_next = ...

部分尝试做。首先,它会尝试评估右侧的内容。这是it_next = whatever。哪个电话it_next.operator = (whatever)。所以你在一个未初始化的对象上调用一个成员函数。这是未定义的行为。达达!!!

3) 所有未定义的行为都很难追踪。这就是为什么您至少应该了解常见情况的原因。

于 2012-10-25T20:53:11.787 回答
7

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
于 2012-10-25T20:59:02.987 回答