在构建调试目标时,什么是构建最佳 g++ 优化级别?

40

当您想要构建可调试的东西时(特别是g ++,但可能与gcc共享答案),最好的-O级别是什么?换句话说,构建“调试”目标而不是“发布”目标时。

在比较-O0和-O1时,gcc在线文档有点含糊不清(此处)。我的解释是,-O1只启用了一种可能影响调试能力的优化,即-fomit-frame-pointer。但引用文档,它仅在不干扰调试的情况下启用了-O1。我的理解正确吗?

这个网站上的另一篇帖子 (在这里) 特别谈到了-O2,答案基本上是“可以工作,但会得到乱序执行”。 依我之见,这可能从令人恼火到灾难性的范围内跳动。


2
g++的开发人员通过精心选择默认优化来回答了这个问题。对于大多数人最有效的级别是在省略-O标志时选择的级别。 - n. m.
3个回答

57

GCC 4.8引入了一个新的优化级别:-Og,最好两个世界都有。

-Og
优化调试体验。-Og启用不会干扰调试的优化。它应该是标准编译调试周期的首选优化级别,既可以提供合理的优化水平,又可以保持快速编译和良好的调试体验。

这样一来就可以进行一些优化,从而获得更好的性能、更好的可能未初始化变量的检测,并且还可以在GDB中逐步执行程序,而不需要在函数之间来回跳转。


3
-Og的优化级别介于-O0-O1之间。另请参见我在这里的回答,其中讨论了各种-O-g级别。 - Lekensteyn
2
在我们使用g++ 4.9测试我们的一个库时,-Og 的构建速度比 -O0 慢了20-25%。这是GCC的一个很好的补充,但基于编译时间的惩罚,我不认为它应该自动成为首选级别。 - Josh Kelley

30
那么...哪些标志适用于调试构建?
任何您感到舒适的调试标志。
当使用-g -O0进行构建时,调试最容易,但代码运行非常缓慢。
当使用-g -O1进行构建时,您将开始观察优化效果。尝试进入函数时,会发现它已被内联等。
使用-g -O2,您会注意到很多优化效果。打印变量时会出现“optimized out”,在代码中会出现意外跳转等。
使用-g -O3,您会看到相同的症状,但更频繁。
GCC实际上没有超过-O3的级别,所以这就是终点。
理解GCC使用-O3执行的转换的人很少有麻烦来调试该代码(您始终可以查看汇编代码,找出要使用的变量实际位于何处,然后从那里开始)。但对于普通人来说,通常很难调试-O2代码。
[1] GDB和GCC目前正在进行降低 optimized out 实例数的工作,但尚未完成。

2
我认为gcc的优化级别不仅仅是-O3,还有更高的-Ofast - Hi-Angel
1
-g 也有不同的级别。 -g 相当于 -g2,例如 -g3 可以添加宏扩展。 - Lekensteyn

-3
调试模式(-g)和优化级别(-O*系列)是独立的问题。 -g 标志基本上指示 gcc 在编译时包括调试符号(以及与代码行号对应的一些提示)。 它可以应用于任何优化级别。
因此,简单的答案是“构建生产程序时最佳的 g++ 优化级别”,这是一个更长的讨论。

1
True、DST和codegen在技术上是正交函数,任何一个函数的任意级别都可以应用于另一个函数。这并不意味着将-g与-O5组合起来会给你任何可读性的东西。这就是为什么任何体面的项目都会有调试和发布目标(或模式或风格)。那么...哪些标志适用于调试构建? - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接