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

标签 c++ iterator valgrind undefined-behavior conditional-operator

我不得不分享这个:

由于以下涉及条件运算符的琐碎错误,我整整挂了 2 天电话。

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

  1. 为什么有错误的代码可以编译?
  2. bug 在做什么?
  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. bug 在做什么?
  3. 为什么很难找到它?

谢谢 children 。

最佳答案

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)。所以您在未初始化的对象上调用成员函数。这是未定义的行为。哒哒!!!

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

关于c++ - 条件运算符中的未定义行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13077042/

相关文章:

c++ - 我能否将 "force"Cachegrind 分析成一个操作(或行)?

C++,valgrind operator new(unsigned int)

java - 确定性语言的适用性

java - 将 C++ 加密转换为 Java

c++,调用函数时不带(),什么意思?

java - 在 Java (Pre-6) TreeMap 和 Iterator 索引和下一个元素之间挣扎

iterator - 有没有一种方法可以删除基于结果进行过滤和分区的迭代器链中项目的展开?

涉及另一个类型名的 C++ 模板优化?

java - 使用 rs.next() 获取所有数组元素

valgrind - 为内存泄漏生成抑制