2、GDB基础命令:run、continue、next、step、break、list、print、quit
调试器这东西,说白了就是给程序装了个「慢放镜头」。GDB 作为 Linux 下最经典的调试工具,我用了十几年,每次带新人时都会先让他们把这几个基础命令练熟。它们就像你工具箱里的螺丝刀和扳手——不一定每次都用得上,但用的时候必须顺手。
2.1 启动与退出:run 和 quit
先说说怎么让程序跑起来。你编译程序时记得加 -g 选项,不然 GDB 没法识别符号信息。我见过太多人忘了这步,然后跑来问我为什么看不到源码。
gcc -g -o myapp myapp.c
gdb ./myapp
进入 GDB 后,输入 run(或者简写 r)就能启动程序。如果程序需要命令行参数,直接跟在后面:
(gdb) run arg1 arg2
退出就简单了,quit(或 q)。嗯,这里要注意:如果你正在调试,GDB 会问你是否要退出,确认一下就行。
run 之前先设好断点,不然程序一下子就跑完了,你连看的机会都没有。
2.2 让程序停下来:break
break 是调试的核心。没有断点,调试就像在黑暗里找东西。你可以按函数名、行号、甚至条件来设断点。
(gdb) break main // 在 main 函数入口
(gdb) break 42 // 在第 42 行
(gdb) break file.c:100 // 在 file.c 的第 100 行
我在项目中遇到过一种情况:一个 bug 只在循环第 5 次时出现。如果每次都手动按 continue 5 次,那效率太低了。这时候条件断点就派上用场:
(gdb) break 100 if i == 5
这样程序只在 i 等于 5 时停下来。省时省力。
info break 检查一下。
2.3 单步执行:next 和 step
这两个命令经常让人混淆。简单来说:next(n)是「跳过函数调用」,step(s)是「进入函数内部」。
| 命令 | 作用 | 适用场景 |
|---|---|---|
next |
执行下一行,不进入函数 | 你只关心当前函数逻辑 |
step |
执行下一行,进入函数内部 | 你想看被调用函数的细节 |
举个例子:
int a = foo(); // 如果在这行用 next,直接得到结果
// 如果用 step,会跳进 foo 函数内部
你想想看,如果你在调试一个库函数,用 step 进去后可能看到一堆底层实现,反而更晕。所以我一般先用 next,确认问题不在当前函数时,再用 step 深入。
2.4 继续执行:continue
continue(c)让程序继续跑,直到遇到下一个断点或程序结束。这个命令看似简单,但配合条件断点用起来非常强大。
(gdb) continue
有时候你设了多个断点,想跳过当前这个,直接跑到下一个。这时候 continue 就是你的「快进键」。
continue 不会重置程序状态,它只是从当前位置继续执行。如果你改了变量值,继续跑时会用新值。
2.5 查看源码和变量:list 和 print
list(l)用来查看源码上下文。默认显示当前行附近的 10 行代码。你可以指定行号或函数名:
(gdb) list // 显示当前行附近
(gdb) list 50 // 显示第 50 行附近
(gdb) list main // 显示 main 函数
print(p)则是查看变量值。这是调试时最常用的命令之一:
(gdb) print i
$1 = 5
(gdb) print &i
$2 = (int *) 0x7fffffffe4a0
你还可以用 print 查看表达式结果:
(gdb) print i * 2
$3 = 10
我曾经用 print 排查过一个诡异的数组越界问题。打印数组元素时发现某个值异常大,顺着索引往回查,才发现是循环条件写错了。
print 的结果会保存在 $1、$2 这样的历史变量里。后面可以直接用 $1 引用,不用重新计算。
2.6 知识体系总览
下面这张图把本章的命令关系梳理了一下。你调试时基本就是在这几个命令之间切换:
2.7 实战组合拳
光记命令没用,得会用。我分享一个常用的调试套路:
- 启动程序:
gdb ./app然后run - 发现问题点:程序崩溃或输出不对,记下位置
- 设断点:在可疑位置
break 行号 - 重新运行:
run,程序停在断点处 - 单步跟踪:用
next或step一步步走 - 查看变量:
print 变量名确认值 - 继续或退出:没问题就
continue,调试完quit
这个流程我用了十年,基本覆盖了 90% 的调试场景。剩下的 10% 需要更高级的技巧,比如条件断点、观察点等,后面章节会讲到。
next 跳过了线程切换,结果漏掉了竞态条件。后来改用 step 配合线程断点才抓到问题。所以单线程用 next 没问题,多线程要小心。
好了,这 8 个命令就是 GDB 调试的基石。你先把它们练熟,后面学高级功能时才能得心应手。记住:调试不是猜谜,而是用工具一步步还原真相。