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

问题描述

当我想调试C或C ++程序时,有人教我使用-O0关闭优化,并使用-ggdb来将符号插入可执行文件中,这些符号针对使用我使用的GNU gdb调试器(或者,您可以将-glldb用于LLVM / clang的lldb调试器,或者仅将-g用于常规调试符号,但这不会显然与-ggdb一样好...)。但是,我最近偶然发现有人说使用-Og(而不是-O0),这让我措手不及。当然,它在man gcc中!:

-Og优化调试体验。 -Og启用不干扰调试的优化。它应该是标准edit-compile-debug周期的最佳选择级别, 提供合理级别的优化,同时保持快速编译和良好的调试体验。

那么,有什么区别?这是-O0中的man gcc描述:

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

man gcc明确指出-Og“应该是标准edit-compile-debug周期的最佳选择级别”。

这听起来像-O0确实是“没有优化”,而-Og是“有一些优化,但只有那些不会干扰调试的优化”。这个对吗?那么,我应该使用哪个?为什么?

相关:

  1. 相关,但不是重复的! (请仔细阅读,绝不是重复的内容):What is the difference between -O0,-O1 and -g
  2. 我关于调试--copt=设置以用于Bazel的答案:gdb: No symbol "i" in current context

解决方法

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

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

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

因此,从现在开始,除了-Og之外,我还使用-O0(不是-ggdb)。


UDPATE 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,我也同意] What does <value optimized out> mean in gdb?