1. 引言
GDB 是 Linux 下最常用的调试工具,用于在程序运行时查看内部状态、定位崩溃原因、跟踪变量变化。
2. 准备工作:安装 GDB 与 CGDB
在开始调试前,需要先安装 GDB。如果希望获得更友好的交互界面,可以同时安装 CGDB(基于 GDB 的文本界面封装)。
bash
sudo yum install -y gdb
sudo yum install -y cgdb
安装完成后,在终端输入 gdb --version 验证是否安装成功。
3. 编译调试版本:-g 选项
要让程序可以被 GDB 调试,编译时必须加上 -g 选项,否则无法进行源码级调试。该选项会在生成的可执行文件中加入调试信息,便于 GDB 定位源码行号和变量。
bash
gcc mycode.c -o mycode -std=c99 -g
其中 -std=c99 指定使用 C99 标准,-g 表示生成调试信息。编译完成后,用 file mycode 可以查看可执行文件是否包含调试信息。
4. 启动 GDB 并查看代码
启动 GDB 并加载可执行文件:
bash
gdb mycode
进入 GDB 交互界面后,常用命令如下:
- list(或 l) :从第一行开始显示源码,默认每次显示 10 行。连续输入
l会继续向下翻页。 - run(或 r):运行当前程序,直到遇到断点或程序结束。
gdb
(gdb) l
(gdb) r
5. 断点管理:打断点、查看、删除
断点是调试的核心,可以让程序在指定行暂停,方便观察变量状态。
- b 行号 :在指定行设置断点,例如
b 12在第 12 行打断点。 - info b:查看当前所有断点,会显示断点编号、位置和状态。
- d 断点编号 :删除指定编号的断点,例如
d 1删除 1 号断点。 - disable 断点编号:暂时取消某个断点的效能,但保留断点。
- enable 断点编号:重新启用被禁用的断点。
gdb
(gdb) b 12
(gdb) info b
(gdb) d 1
(gdb) disable 2
(gdb) enable 2
注意:如果本次调试会话不退出,断点编号会持续累加,不会因为删除而重新编号。
6. 单步执行:逐过程与逐语句
程序在断点处暂停后,可以使用以下命令逐步执行:
- next(或 n,对应 F10):逐过程执行,遇到函数调用时一次性跳过,不进入函数内部。
- step(或 s,对应 F11):逐语句执行,遇到函数调用时会进入函数内部继续调试。
gdb
(gdb) n
(gdb) s
GDB 会自动执行最新一条指令,因此直接按回车可以重复上一条命令。
7. 查看变量与继续运行
程序暂停后,可以通过以下命令查看变量状态、继续运行或跳出当前函数:
- p 变量名 :打印变量的当前值,例如
p i查看变量 i 的值。 - c:继续运行,直到遇到下一个断点或程序结束。
- until 行号 :运行到指定行号后暂停,例如
until 20运行到第 20 行。 - finish:运行完当前函数并返回,适合在逐语句进入函数后快速跳出。
- display 变量名 :每次暂停时自动打印指定变量的值,例如
display i。 - undisplay 编号 :取消某个自动显示项,编号可通过
info display查看。 - info locals:展示当前函数内部所有临时变量的名称和值。
gdb
(gdb) p i
(gdb) c
(gdb) until 20
(gdb) finish
(gdb) display i
(gdb) undisplay 1
(gdb) info locals
8. 实战示例:完整调试流程
下面用一个简单的 C 程序演示完整调试流程。假设文件 mycode.c 内容如下:
c
#include <stdio.h>
int main() {
int i;
int sum = 0;
for (i = 1; i <= 5; i++) {
sum += i;
}
printf("sum = %d\n", sum);
return 0;
}
调试步骤:
bash
gcc mycode.c -o mycode -std=c99 -g
gdb mycode
gdb
(gdb) l
(gdb) b 6
(gdb) r
(gdb) p i
(gdb) n
(gdb) p sum
(gdb) c
(gdb) quit
通过以上步骤,可以观察循环中变量 i 和 sum 的变化,验证程序逻辑是否正确。
9. 常用指令速查表
| 指令 | 作用 |
|---|---|
| gcc -g | 编译时添加调试信息 |
| list / l | 从第一行开始显示源码 |
| run / r | 运行程序 |
| b 行号 | 在指定行打断点 |
| info b | 查看所有断点 |
| d 断点编号 | 删除指定断点 |
| disable / enable | 取消 / 启用断点效能 |
| next / n(F10) | 逐过程执行 |
| step / s(F11) | 逐语句执行 |
| p 变量名 | 打印变量值 |
| c | 运行到下一个断点 |
| until 行号 | 运行到指定行 |
| finish | 运行完当前函数并返回 |
| display / undisplay | 设置 / 取消自动显示变量 |
| info locals | 展示当前函数内部临时变量 |