编译器的`-O0`选项和`-Og`选项有什么区别?

问题描述 投票:0回答:2

当我想要调试 C 或 C++ 程序时,我被教导使用

-O0
关闭优化,并使用
-ggdb
将符号插入到可执行文件中,这些符号针对使用 GNU
gdb
调试器进行了优化,我使用它(或者,您可以将
-glldb
用于 LLVM/clang 的
lldb
调试器,或者仅使用
-g
作为一般调试符号,但这显然不如
-ggdb
好......)。然而,我最近偶然发现有人说使用
-Og
(而不是
-O0
),这让我措手不及。果然,它在
man gcc
!:

-Og
优化调试体验。
-Og
实现不干扰调试的优化。它应该是标准编辑-编译-调试周期选择的优化级别, 提供合理的优化水平,同时保持快速编译和良好的调试体验。

那么,有什么区别呢?这是来自

-O0
man gcc
描述:

-O0
减少编译时间并使调试产生预期结果。这是默认值。

man gcc
明确表示
-Og
“应该是标准编辑-编译-调试周期选择的优化级别”。

这听起来像

-O0
确实是“无优化”,而
-Og
是“进行了一些优化,但仅限于那些不干扰调试的优化”。它是否正确?那么,我应该使用哪个,为什么?

相关:

  1. 相关,但不重复! (仔细阅读,它根本不是重复的):-O0、-O1 和 -g 之间有什么区别
  2. 我对调试的回答
    --copt=
    与Bazel一起使用的设置:gdb:当前上下文中没有符号“i”
c++ c debugging gdb compiler-optimization
2个回答
8
投票

快速总结

不要使用-Og

使用

-ggdb -O0

(首选),或 
-g -O0
 代替。

-Og

 中断调试。

详情

@kaylum 刚刚在我的问题下的评论中提供了一些很棒的见解!我最关心的关键部分是:

[

-Og

] 是比 -O0 更好的生成可调试代码的选择,因为一些收集调试信息的编译器通道在 -O0 处被禁用。

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options

所以,从现在开始,除了 -Og

 之外,我还使用 
-O0
(不是 
-ggdb
)。


UDP日期 2020 年 8 月 13 日:

见鬼!没关系。我坚持-O0

使用

-Og

 我到处都遇到 
<optimized out>
Can't take address of "var" which isn't an lvalue.
 错误!我无法再打印我的变量或检查它们的内存!例如:

(gdb) print &angle Can't take address of "angle" which isn't an lvalue. (gdb) print angle_fixed_p $6 = <optimized out>
但是,有了

-O0

,一切都很好!

(gdb) print angle $7 = -1.34869879e+20 (gdb) print &angle $8 = (float *) 0x7ffffffefbbc (gdb) x angle 0x8000000000000000: Cannot access memory at address 0x8000000000000000 (gdb) x &angle 0x7ffffffefbbc: 0xe0e9f642

所以,回到使用 -O0

 而不是 
-Og

相关:

    [他们也推荐
  1. -O0
    ,我也同意]
    在gdb中是什么意思?

1
投票
由于编辑的原因,从上面的

Gabriel的优秀答案

中,添加
-ggdb并不完全清楚。 我发现,如果 GDB 是您首选的调试器,那么与 -O0
 一起使用 
-ggdb3
 绝对是有利的(
3
 很重要,比仅仅使用 
ggdb
 更好)。

© www.soinside.com 2019 - 2024. All rights reserved.