必须用 gcc -g 编译,否则 gdb 无法加载符号表,导致 list 显示“No symbol table is loaded”;Makefile 中应通过 CC = gcc -g 或 CFLAGS = -g -Wall 统一注入调试信息,并配合 make clean 和正确路径确保源码与符号匹配。

必须用 gcc -g 编译,否则 gdb 读不到源码和变量信息,所有调试操作都成空谈。
Makefile 里必须加 -g 参数
很多人写完 Makefile 直接 make,结果 gdb ./main 进去后 list 显示 “No symbol table is loaded”,就是忘了加调试信息。
-
CC = gcc -g是最稳妥的写法,把-g固定进编译器变量 - 不要只在某一行命令里临时加
-g,比如gcc -c main.c -o main.o没加,那main.o就没调试信息,链接后整个可执行文件也会丢掉这部分 - 如果用了
CFLAGS,确保它包含-g,例如:CFLAGS = -g -Wall -std=c99 - 检查是否真生效:编译完运行
file ./main,输出里要有 “with debug_info”;或者size ./main对比不加-g的大小,明显变大才对
gdb 启动前别跳过 make clean
改了源码但没清旧 .o 文件,make 可能直接复用老目标,导致 gdb 加载的仍是旧符号——断点打在新行上却停不住,或 print 出来的是旧变量值。
- 每次改完关键逻辑,尤其涉及函数签名、变量作用域时,先
make clean(前提是 Makefile 里写了clean规则) - 确认
clean规则用了.PHONY,否则万一当前目录下真有个叫clean的文件,make clean就会静默跳过 - 一个最小可用的
clean规则长这样:clean: \t-rm -f *.o *.out ./main
(注意\t是真正的 Tab 字符,不是空格)
调试时别依赖默认目标名
Makefile 第一个目标是默认目标,但你 gdb 调的未必是它。比如你写了 test: test.o utils.o 在第一行,但实际想调 demo,make 之后却去 gdb ./test,白忙活。
- 明确指定要构建的目标:
make demo,再gdb ./demo - 用
make -n预览实际执行的命令,确认编译参数、输出文件名、是否真用了-g - 如果 Makefile 里用了自动变量(如
$@,$^),在gdb里查问题时,得心里清楚当前加载的是哪个目标对应的二进制——info files能立刻告诉你它从哪读的符号
最容易被忽略的一点:gdb 加载可执行文件时,工作路径和源码路径必须一致,或者你得用 directory 命令手动告诉它源码在哪;否则 list 或设置断点会失败,报 “No such file or directory”。











