问题描述
当我想调试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
是“有一些优化,但只有那些不会干扰调试的优化”。这个对吗?那么,我应该使用哪个?为什么?
相关:
- 相关,但不是重复的! (请仔细阅读,绝不是重复的内容):What is the difference between -O0,-O1 and -g
- 我关于调试
--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
吧!
相关:
- [他们也推荐
-O0
,我也同意] What does <value optimized out> mean in gdb?