编译器优化会导致程序崩溃

lee*_*mes 5 c++ qt g++ compiler-optimization

我正在用C++/Qt编写一个包含图形文件解析器的程序.我g++用来编译项目.

在开发过程中,我不断比较不同编译器标志之间关于优化和调试信息的低级解析器层的性能,以及Qt的调试标志(打开/关闭qDebug()和Q_ASSERT()).

现在我遇到的问题是,唯一正常运行的构建是没有任何优化的构建.所有其他版本,即使有-O1,似乎以另一种方式工作.它们由于不满意的断言而崩溃,这些断言在没有-O...标志的情况下编译时会得到满足.即使使用,代码也不会产生任何编译器警告-Wall.

我非常确定我的程序中存在一个错误,这似乎只对启用优化有害.问题是:即使在调试程序时我也找不到它.解析器似乎从文件中读取错误的数据.当我运行一些简单的测试用例时,它们运行得很好.当我运行一个更大的测试用例(直接从文件读取的图形上的路由计算)时,文件中的读取不正确,我无法解释.

我应该从哪里开始追踪这种未定义行为的问题?这种不同的行为可能涉及哪些优化方法?(我可以一个接一个地启用所有标志,但我不知道那么多编译器标志,但-O...我知道它们有很多,所以这需要很长时间.)一旦我知道哪种类型这个bug是,我相信我迟早会发现它.

如果你能告诉我哪些编译器优化方法可能成为这些问题的候选者,你可以帮助我很多.

Raf*_*sta 16

在优化的构建中通常会出现一些类错误,这些错误通常不会出现在调试版本中.

  1. 未初始化的变量.编译器可以捕获一些但不是全部.查看所有构造函数,查看全局变量.特别是寻找未初始化的指针.在调试中,构建内存重置为零,但在发布版本中则不是.

  2. 使用超出范围的临时工.例如,当您在函数中返回对本地临时的引用时.这些通常在调试版本中工作,因为堆栈被填充更多.临时者倾向于在堆叠上存活一段时间.

  3. 阵列覆盖临时写作.例如,如果在函数中创建一个数组作为临时数,然后在结尾之外写入一个元素.同样,堆栈将在调试中有额外的空间(用于调试信息),并且您的溢出将不会命中程序数据.