C++ 带有O1、O2或O3的gcc 4.7.3会产生错误代码
在gcc 4.7.3中,我的应用程序运行良好,无需优化, 但当我使用-O1、-O2或-O3时,会发生一件奇怪的事情: 非空指针从一步到下一步变为空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
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?以下是如何调试它
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