当我想要调试 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
是“进行了一些优化,但仅限于那些不干扰调试的优化”。它是否正确?那么,我应该使用哪个,为什么?
--copt=
与Bazel一起使用的设置:gdb:当前上下文中没有符号“i”不要使用-Og
。使用
-ggdb -O0
(首选),或
-g -O0
代替。
-Og
中断调试。详情
[
-Og
] 是比 -O0 更好的生成可调试代码的选择,因为一些收集调试信息的编译器通道在 -O0 处被禁用。
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options
所以,从现在开始,除了 -Og
之外,我还使用
-O0
(不是
-ggdb
)。
见鬼!没关系。我坚持-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
,我也同意]在gdb中是什么意思?
Gabriel的优秀答案
中,添加
-ggdb
并不完全清楚。
我发现,如果 GDB 是您首选的调试器,那么与 -O0
一起使用
-ggdb3
绝对是有利的(
3
很重要,比仅仅使用
ggdb
更好)。