2、GDB基本命令:启动程序、设置断点、运行控制、查看变量、单步执行

说实话,很多初学者一上来就想着用GDB搞多线程、搞core dump分析,结果连最基本的启动和暂停都搞不明白。我当年也是这样,拿着gdb ./a.out敲下去,然后盯着(gdb)提示符发呆——接下来该干嘛?

别急,这一章咱们就把最核心的五个操作吃透。你想想看,调试的本质是什么?说白了就是:让程序停下来,看看它里面发生了什么。这五个命令就是干这个的。

核心思想:调试不是乱试,而是有节奏地控制程序执行,在关键位置停下来检查状态。

2.1 启动程序:run 与 start

启动程序有两种方式,我习惯根据场景来选。

命令 作用 适用场景
run(或 r) 直接运行程序,直到遇到断点或结束 已经设置好断点,想快速跑到第一个断点处
start 在 main 函数入口处暂停 想从程序入口一步步看初始化逻辑

举个例子,假设你有一个 test.c:

#include <stdio.h>

int main() {
    int a = 10;
    int b = 20;
    int c = a + b;
    printf("c = %d\n", c);
    return 0;
}

编译时记得加 -g 选项:

gcc -g -o test test.c

然后启动GDB:

gdb ./test

在 (gdb) 提示符下,如果你敲 start,程序会在 main 函数的第一行停下来。如果你敲 run,它会直接跑完——除非你提前设了断点。

我的习惯:刚开始调试时,我一般先用 start,从入口处一步步跟。等熟悉了代码流程,再用 run 配合断点快速定位。

2.2 设置断点:break 的三种常用姿势

断点就是让程序停下来的「路障」。GDB里设置断点用 break(简写 b)。我总结了三种最常用的写法:

  • 按行号设置:break 10 —— 在源文件的第10行停下
  • 按函数名设置:break main —— 进入 main 函数时停下
  • 按条件设置:break 10 if a == 5 —— 只有变量 a 等于 5 时才停下

我在项目中遇到过一个问题:一个循环跑了十万次,我想在某个特定条件下停下来。如果手动按 c(继续)十万次,手都得废掉。这时候条件断点就派上用场了:

(gdb) break 15 if i == 99999

嗯,这个技巧帮我省了不少时间。

注意:条件断点中的表达式必须是 C/C++ 合法的。比如 if a = 5 是赋值,不是比较,GDB不会报错但逻辑是错的。我曾经在这上面栽过跟头,排查了半天才发现是少写了一个等号。

2.3 运行控制:continue 与 中断

程序停下来了,怎么让它继续跑?用 continue(简写 c)。

但有时候你跑着跑着发现不对劲,想手动中断——按 Ctrl + C 就行。GDB会捕获这个信号,把程序停在当前执行的位置。

我记得有一次调试一个死循环,程序跑起来就卡死了。我按了 Ctrl + C,GDB停在了循环体里,我一看——哦,循环变量忘了递增。这种问题用肉眼扫代码很难发现,但一跑起来就原形毕露。

2.4 查看变量:print 与 display

程序停下来了,接下来就是「看看里面有什么」。最常用的命令是 print(简写 p):

(gdb) print a
$1 = 10
(gdb) print &a
$2 = (int *) 0x7fffffffe4a4
(gdb) print sizeof(a)
$3 = 4

print 可以打印变量值、地址、甚至表达式结果。比如 print a + b 会直接算出结果。

但如果你每次单步后都想看某个变量,每次都敲 print 就太累了。这时候用 display:

(gdb) display a
1: a = 10

之后每次程序停下来,GDB都会自动显示 a 的值。不想看了就用 undisplay 取消。

小技巧:用 info locals 可以一次性查看当前函数的所有局部变量。我调试复杂函数时经常先用这个命令「扫一眼」全局状态。

2.5 单步执行:step 与 next

单步执行是调试的「显微镜」。两个命令的区别很关键:

命令 简写 行为
step s 进入函数内部
next n 不进入函数,直接执行完当前行

举个例子,假设当前停在 printf("c = %d\n", c); 这一行:

  • 敲 next:直接执行完 printf,停在下一行
  • 敲 step:会进入 printf 函数内部(如果你有它的源码)

我个人习惯是:确认函数没问题就用 next,怀疑函数有 bug 就用 step 进去看。别傻乎乎地每个函数都 step 进去,标准库函数里面几千行代码,你进去干嘛?

避坑指南:我曾经在调试一个第三方库时,习惯性地用了 step,结果一头扎进了汇编代码里。当时我连寄存器都看不懂,差点崩溃。后来学乖了——不确定的函数先用 next 跳过,真有必要再 step。

知识体系总览

下面这张图把本章的核心逻辑串起来了。你可以把它当作调试时的「操作地图」:

GDB基本命令操作流程 启动程序 run / start 设置断点 break / 条件断点 运行控制 continue / Ctrl+C 查看变量 print / display 操作要点 • 先设断点,再run • 条件断点省时间 • Ctrl+C 随时中断 • display 自动跟踪 • next 跳过函数 • step 进入函数 • info locals 扫全局 • 先next后step • 别进标准库内部

这张图展示的就是调试时的基本节奏:启动 → 设断点 → 运行 → 查看 → 单步。循环往复,直到找到问题。

好了,这一章的内容就到这里。五个命令,不多,但每一个都是调试的基石。你可以在自己的代码上试试,从 start 开始,用 next 一步步走,用 print 看看变量变化——相信我,这种感觉比盯着代码猜要踏实得多。

可可精品资料库