C++ 带有O1、O2或O3的gcc 4.7.3会产生错误代码

C++ 带有O1、O2或O3的gcc 4.7.3会产生错误代码,c++,gcc,C++,Gcc,在gcc 4.7.3中,我的应用程序运行良好,无需优化, 但当我使用-O1、-O2或-O3时,会发生一件奇怪的事情: 非空指针从一步到下一步变为空 iResult = ppAG[0]->prune(bCut); if (iResult >= 0) { printf("save %p in [%s]\n", ppAG[0], sOutput); ppAG[0]->saveBin(sOutput); printf("showing ancestorinfo

在gcc 4.7.3中,我的应用程序运行良好,无需优化, 但当我使用-O1、-O2或-O3时,会发生一件奇怪的事情: 非空指针从一步到下一步变为空

iResult = ppAG[0]->prune(bCut);
if (iResult >= 0) {
    printf("save %p in [%s]\n", ppAG[0], sOutput);
    ppAG[0]->saveBin(sOutput);
    printf("showing ancestorinfo for %p\n", ppAG[0]);
    ppAG[0]->showAncestorInfo(false);
}
带有
saveBin
的行执行得很好,但在下一行它崩溃了。 调试器显示,当我从第四行跳到第五行时,ppAG变为NULL

有趣的是,当我注释掉对
prune
的调用时,代码没有崩溃, 即使
prune
仅包含打印语句

我用valgrind检查过:未优化的代码没有错误,对于优化的代码,我只得到

----(snip)----
save 0x64d1780 in [smalltest_040.ag]
==15401== Invalid read of size 8
==15401==    at 0x402D86: main (stdio2.h:104)
==15401==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
----(snip)----
我怀疑这在第五行的打印声明中

对于gcc 4.6.3,这不会发生


对这种行为有何解释,还是它是一个bug?

以下是如何调试它

  • 在GDB下运行程序,并在
    saveBin
    行上设置断点:

    (gdb) break <file>:<line>
    
  • ppAG[0]
    创建观察点:

    (gdb) watch ppAG[0]
    
  • 让程序继续:

    (gdb) continue
    
  • 然后,程序应该在将
    NULL
    写入指针的指令上停止。然后,您可以
    回溯
    列表
    分解
    ,检查
    信息注册表
    ,以缩小问题范围


    这可能是堆栈上的缓冲区溢出(valgrind通常会在堆上检测到),或者是行为未定义的条件,或者可能只是一个真正的编译器错误。

    一个编译器在打开优化的情况下生成“错误”代码,几乎总是错误代码,因此是您自己的错误。你可能在某个地方有UB。听起来很像你有缓冲区溢出的内存泄漏。请检查之前运行的代码,确保未使用未初始化的变量或指针。顺便说一句。我们已经发布了gcc 4.8和4.9。在任何情况下,在不知道你的代码是什么的情况下,我们都不能说它是否正确。@MatsFredriksson OP说valgrind没有发现他的代码有任何错误,尽管我们不应该认为这保证了什么…调试优化的构建可能是一种幻觉-代码的执行顺序不再与源代码匹配,断点不在您认为的位置,变量会神秘地改变值。您需要查看组件以了解发生了什么。很可能你在某个地方有未定义的行为(几乎可以在任何地方,甚至在事情变得怪异之后)。@asm:谢谢-这帮了大忙。正如您(和Mats)所建议的那样,我能够找到我在缓冲区外书写的位置。现在,优化版本也可以正常运行。
    (gdb) continue