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

时间:2014-07-01 11:03:54

标签: c++ gcc

使用gcc 4.7.3我的应用程序工作正常,没有优化, 但是当我使用-O1,-O2或-O3时会发生一件奇怪的事情: 非NULL指针从一步到下一步变为NULL。

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)----

我怀疑这是在第五行的print语句中。

使用gcc 4.6.3,这不会发生。

是否有对此行为的解释,还是错误?

1 个答案:

答案 0 :(得分:3)

以下是调试方法。

  1. 在GDB下运行您的程序,并在saveBin行设置断点:

    (gdb) break <file>:<line>
    
  2. 让程序达到这一点:

    (gdb) run
    
  3. ppAG[0]创建一个观察点:

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

    (gdb) continue
    
  5. 然后程序应该停止将NULL写入指针的指令。然后,您可以backtracelistdissassemble,检查info reg以缩小问题范围。

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