-g是gdb调试的硬性前提,必须添加才能生成dwarf调试信息,使gdb可识别变量名、行号、函数结构;不加则符号被剥离,导致无法设断点、查变量或列出源码。

必须加 -g 编译,否则 GDB 看不到变量名、行号和函数结构——这不是可选项,是硬性前提。
为什么 -g 不是“加了更好”,而是“不加就废”
没有 -g 的可执行文件里,所有符号(比如 main、count、buf)在链接后基本被剥离或重命名成 _Z3fooi 这类名字。GDB 启动后执行 l(list)会报 No symbol table is loaded;设断点用 b main 会提示 Function main not defined;查变量 p i 直接失败。
-g 让 GCC 在二进制中嵌入 DWARF 调试信息,GDB 靠它把机器指令映射回源码行、还原变量作用域、识别结构体成员。不加它,GDB 就只剩反汇编和寄存器操作,等于蒙眼修电路。
-
-g是最低可用等级,日常开发够用 -
-g3会包含宏定义、#define值、内联展开细节,调试复杂宏逻辑时有用,但生成文件大 60%–80% -
-O2 -g可以共存,但注意:优化可能让变量被分配到寄存器、被合并、甚至被删掉,p查不到值或显示<optimized out></optimized>
从编译到启动 GDB 的最小可行链路
别跳步。漏掉任一环节,GDB 就无法关联源码。
- 写好
test.c,确保保存(Vim 中别忘了:w) - 用
gcc -g test.c -o test编译 —— 注意不是gcc test.c -o test - 确认文件存在:
ls -l test,大小应明显大于不加-g的版本(通常 >100KB) - 运行
file test,输出里必须含with debug_info - 启动调试:
gdb ./test(路径不能省,否则 GDB 找不到符号文件)
进了 (gdb) 提示符后,立刻输 l。如果看到源码片段,说明成功;如果报错,回头检查上一步是否漏了 -g 或路径写错。
GDB 里最常卡住的三个操作及解法
新手常在这三步反复失败,本质都是没理解 GDB 的“状态依赖”:
-
设不了断点:先确认已用
l看到源码;再用b 10(行号)或b main(函数名);若提示Function main not defined,99% 是没加-g或编译用了-s(strip) -
p查不到变量:检查是否在该变量作用域内(比如在for循环外p i就无效);若显示<optimized out></optimized>,说明用了-O2以上且未加-g兼容优化,换-O0 -g重编 -
运行后直接退出,没停在断点:确认已执行
r(run),不是只输gdb ./test就以为启动了;若程序秒退,可能是段错误,此时用r后立刻输bt(backtrace)看崩溃位置
真正难的从来不是命令记多少,而是每次 gdb 报错时,能快速判断是编译环节断了(缺 -g)、路径没对上(gdb 加载错文件)、还是当前执行流根本没走到你设断点的地方。这三个点,任何一个出问题,整个调试链条就失效。











