list默认以当前行为中心显示上下各5行共10行源码,严格锚定暂停位置;若显示空白或报错,主因是未加-g编译、源码路径不匹配或无对应C源码。

程序停住后,list 默认显示当前行附近代码
只要程序被断点、信号或 Ctrl+C 中断,GDB 就会自动定位到暂停位置。此时直接输入 list(或简写 l),GDB 会以当前行为中心,显示上下各 5 行(共 10 行)的源码。如果当前行靠近文件开头或结尾,它会自动调整范围,但始终保证当前行可见。
常见误区是以为 list 总是从第 1 行开始——其实不会,它严格锚定在暂停点。如果没看到预期代码,大概率是没加载符号表(编译时没加 -g)或源码路径不对。
info program 和 backtrace 能确认执行位置和调用链
info program 显示程序状态,包括是否运行、暂停原因、当前线程 ID;而 backtrace(或 bt)能立刻告诉你“现在在哪一层函数里”,输出格式类似:
(gdb) bt #0 func (n=250) at test.c:6 #1 0x08048524 in main (argc=1, argv=0xbffff674) at test.c:30
第一行的 test.c:6 就是精确的文件名与行号。注意:如果只看到地址(如 0x08048524)而没有文件行号,说明调试信息缺失或源码不可达。
- 确保编译时用了
gcc -g(不是-O2之类优化选项覆盖了调试信息) - 运行 GDB 前,确认当前目录下有对应源文件,或用
dir /path/to/src添加搜索路径 -
bt输出中若含??或只有地址,基本可判定符号未加载成功
用 frame 查看当前栈帧的完整上下文
frame(或 f)命令比 bt 更聚焦:它只打印当前栈层的函数名、参数值、源文件路径、行号和正在执行的语句。例如:
(gdb) frame #0 func (n=250) at test.c:6 6 int x = n * 2;
这比单纯看行号更可靠,因为它同时验证了变量作用域和执行点。如果你在多线程环境里调试,frame 还会标明当前线程 ID,避免误判其他线程的暂停位置。
容易忽略的一点是:frame 不会自动刷新——如果程序继续执行后又暂停,需重新执行该命令才能看到新位置。
为什么有时 list 显示空白或报错?
最常见三个原因:
- 源码文件被移动或删除,GDB 找不到
test.c,此时list报Cannot find source file - 二进制是用不同路径编译的(比如在 /build/ 下编译,但你在 /src/ 下启动 GDB),需用
set substitute-path /build/ /src/ - 程序由汇编或内联函数触发暂停,而该位置无对应 C 源码行,
list就会显示空或跳转到最近的有源码行
这时候别硬等 list 出结果,先用 info registers 看 $rip(x86_64)或 $pc(ARM),再配合 x/i $rip 查反汇编,往往比死磕源码更快定位问题本质。


















