-g的作用是生成dwarf格式调试信息,使gdb能关联源码行号、函数名和变量名;必须配合-o0使用,并确保所有编译步骤(含静态库)均添加该参数。

-g 是保留调试符号信息最直接、最常用的方式。不加它,GDB 就看不到函数名、行号、变量名,基本没法单步或 print。
为什么加 -g 才能调试
GCC 默认编译出来的二进制里不含源码映射关系——比如哪一行对应哪条机器指令、变量存在哪个寄存器或栈偏移。这些信息被剥离后,GDB 只能看到汇编和内存地址,无法关联到 C 源文件。-g 告诉编译器把这类元数据(DWARF 格式)写进可执行文件或目标文件中。
-g 和 -ggdb 有什么区别
两者都生成调试信息,但格式和兼容性不同:
-
-g:生成标准 DWARF 格式,兼容 GDB、LLDB、Valgrind 等多数工具 -
-ggdb:专为 GDB 优化,可能包含额外注解(如宏展开细节),但某些老版本 GDB 或非 GNU 工具可能解析不全 - 日常开发用
-g就够了;若明确只用 GDB 且需要更细粒度信息(比如内联函数调试),可试-ggdb
容易忽略的两个关键点
加了 -g 不代表一定能顺利调试,还得避开这两个常见坑:
-
别和
-O2或-O3一起用:优化会重排代码、内联函数、删掉未用变量,导致 GDB 显示的“当前行”和实际执行逻辑错位,step跳来跳去,print变量显示<optimized out></optimized> -
Makefile / CMake 中要全局加
-g:只给主程序加没用,如果用了静态库或自建 .o 文件,每个gcc -c步骤也得带-g,否则链接后缺失部分符号
怎么确认符号真加上了
别光信命令有没有敲对,用这几条命令当场验证:
- 检查是否含调试段:
readelf -S your_program | grep debug—— 有.debug_*行就说明成功 - 快速看 GDB 能否加载:
gdb -q ./your_program,如果开头显示Reading symbols from ./your_program...done.就没问题 - 反例:如果显示
(no debugging symbols found),八成是漏加-g,或者用了 strip 清除了符号
-g 没加,而是某个 .o 文件忘了加,或者被后续的 strip 命令干掉了。











