GDB 命令速查表
GDB 的命令可以分为几个大类:启动与程序控制、断点管理、查看数据、执行控制、线程与进程、以及辅助命令。

启动与程序控制
这些命令用于加载程序、设置参数并控制其执行流程。
| 命令 | 缩写 | 描述 | 示例 |
|---|---|---|---|
file |
(无) | 加载一个可执行文件到 GDB 中。 | file my_program |
run |
r |
启动被调试的程序,可以附带参数。 | run arg1 arg2 |
args |
(无) | 设置 run 命令的参数,不执行程序。 |
args --help -v |
kill |
k |
终止当前正在调试的进程。 | kill |
quit |
q |
退出 GDB。 | quit |
start |
(无) | 开始执行程序,但在 main 函数的第一行代码前停住。 |
start |
断点管理
断点是调试的核心,用于在特定位置暂停程序执行。
| 命令 | 缩写 | 描述 | 示例 |
|---|---|---|---|
break |
b |
设置断点。 | |
b <行号> |
在指定行号设置断点。 | b 42 |
|
b <函数名> |
在函数入口处设置断点。 | b main |
|
b <文件名>:<行号> |
在指定文件的行号设置断点。 | b utils.cpp:100 |
|
b *<地址> |
在内存的特定地址设置断点。 | b *0x0804856b |
|
tbreak |
tb |
设置临时断点,程序第一次停住后会自动删除。 | tbreak loop |
info breakpoints |
info b |
查看当前所有断点的信息。 | info b |
delete |
d |
删除一个或所有断点。 | |
delete <断点号> |
删除指定编号的断点。 | delete 1 |
|
delete |
删除所有断点。 | delete |
|
disable |
(无) | 禁用一个断点,但保留它。 | disable 1 |
enable |
(无) | 启用一个被禁用的断点。 | enable 1 |
condition <断点号> <表达式> |
(无) | 设置断点条件,只有当表达式为真时,断点才触发。 | condition 2 i == 10 (断点2在i等于10时触发) |
watch |
(无) | 设置观察点,当变量的值发生变化时暂停程序。 | watch my_var |
rwatch |
(无) | 设置观察点,当变量被读取时暂停。 | rwatch my_var |
awatch |
(无) | 设置观察点,当变量被读取或写入时暂停。 | awatch my_var |
查看数据
程序暂停后,使用这些命令来检查变量、内存和程序状态。
| 命令 | 缩写 | 描述 | 示例 |
|---|---|---|---|
print |
p |
打印一个变量或表达式的值。 | p i |
display |
(无) | 添加一个自动显示项,每次程序停止时,GDB 会自动打印该变量的值。 | display my_array |
info display |
(无) | 查看所有自动显示项。 | info display |
undisplay <编号> |
(无) | 删除一个自动显示项。 | undisplay 1 |
info locals |
(无) | 打印当前栈帧中所有局部变量的值。 | info locals |
info args |
(无) | 打印当前函数的参数值。 | info args |
x |
(无) | 检查内存内容。x/<n><f><u> 是其格式。 |
|
x/20xw &my_var |
从 my_var 的地址开始,以16进制(x)、4字节(w)为单位,打印20个(20)单位。 |
x/20xw &my_var |
|
ptype <变量名> |
(无) | 打印一个变量的类型定义。 | ptype my_struct |
backtrace |
bt |
打印函数调用栈(堆栈跟踪)。 | bt |
frame <n> |
f <n> |
切换到栈帧编号为 n 的帧。 |
frame 2 |
up |
(无) | 向上移动一帧(调用者方向)。 | up |
down |
(无) | 向下移动一帧(被调用者方向)。 | down |
执行控制
控制程序如何一步步地执行。

| 命令 | 缩写 | 描述 | 示例 |
|---|---|---|---|
continue |
c |
从当前点继续执行程序,直到遇到下一个断点或程序结束。 | c |
next |
n |
执行下一行源代码,如果该行有函数调用,则不会进入函数内部。 | n |
step |
s |
执行下一行源代码,如果该行有函数调用,则会进入函数内部。 | s |
finish |
(无) | 继续执行,直到当前函数返回。 | finish |
until |
u |
在一个循环中,执行到循环体外。 | u |
return |
(无) | 强制从当前函数返回,可以指定一个返回值。 | return 0 |
jump <行号或地址> |
j |
让程序跳转到指定的行或地址继续执行。 | jump 50 |
线程与进程
调试多线程或多进程程序时使用。
| 命令 | 缩写 | 描述 | 示例 |
|---|---|---|---|
info threads |
(无) | 显示所有线程的列表。 | info threads |
thread <线程ID> |
(无) | 切换到指定的线程进行调试。 | thread 2 |
break ... thread <线程ID> |
(无) | 只在指定线程的特定位置设置断点。 | b main thread 3 |
info inferiors |
(无) | 显示所有被调试的进程。 | info inferiors |
inferior <进程ID> |
(无) | 切换到指定的进程进行调试。 | inferior 2 |
辅助命令
这些命令帮助您更好地使用 GDB。
| 命令 | 缩写 | 描述 | 示例 |
|---|---|---|---|
help |
h |
显示命令的帮助信息。 | help print |
list |
l |
列出源代码,默认显示当前行及之后的10行。 | l |
list <行号> |
从指定行号开始列出代码。 | l 100 |
|
list <函数名> |
列出指定函数的代码。 | list main |
|
directory |
dir |
添加源代码搜索路径。 | dir /path/to/src |
shell |
sh |
在不退出 GDB 的情况下执行一个 shell 命令。 | shell ls -l |
set |
(无) | 设置 GDB 内部变量或选项。 | set confirm off (禁用确认提示) |
show |
(无) | 显示 GDB 变量或选项的当前值。 | show confirm |
实战调试流程示例
假设我们有一个简单的 C++ 程序 buggy.cpp:
// buggy.cpp
#include <iostream>
int add(int a, int b) {
int sum = a + b;
std::cout << "Inside add: a=" << a << ", b=" << b << std::endl;
return sum;
}
int main() {
int x = 10;
int y = 20;
int result = add(x, y);
std::cout << "Result: " << result << std::endl;
// Bug: 这里我们想让 y 变成 30,但忘了赋值
y = 30;
result = add(x, y);
std::cout << "New Result: " << result << std::endl; // 这行会输出 30,但我们期望是 40
return 0;
}
编译时务必加上 -g 选项,以包含调试信息!

g++ -g buggy.cpp -o buggy
调试步骤:
-
启动 GDB 并加载程序
gdb ./buggy
-
设置断点 我们想在
main函数和add函数入口都设置断点。(gdb) break main Breakpoint 1 at 0x555555555169: file buggy.cpp, line 10. (gdb) break add Breakpoint 2 at 0x55555555514d: file buggy.cpp, line 4. -
运行程序
(gdb) run Starting program: /path/to/buggy Breakpoint 1, main () at buggy.cpp:10 10 int x = 10; -
查看变量并单步执行 程序在
main函数的第一行停住了,我们来查看x和y的值,然后单步执行。(gdb) print x $1 = 10 (gdb) print y $2 = 4198432 // y 是未初始化的垃圾值 (gdb) next 11 int y = 20; (gdb) next 12 int result = add(x, y); (gdb) print y $3 = 20 // y 被正确赋值为 20 -
进入函数并观察调用栈 现在我们执行到
add(x, y)这一行,使用step进入函数。(gdb) step add (a=10, b=20) at buggy.cpp:4 4 int sum = a + b; (gdb) backtrace #0 add (a=10, b=20) at buggy.cpp:4 #1 0x00005555555551a7 in main () at buggy.cpp:12 -
继续执行 我们可以
continue执行,直到程序结束或下一个断点。(gdb) continue Continuing. Inside add: a=10, b=20 Result: 30 Breakpoint 1, main () at buggy.cpp:10 10 int x = 10; -
发现 Bug 程序再次在
main函数的第一行停住,这说明main函数执行完了又从头开始?不,GDB 在main函数开始处停住是因为break main断点,我们继续执行。(gdb) continue Continuing. Inside add: a=10, b=30 New Result: 30 <-- BUG HERE! Expected 40. [Inferior 1 (process 12345) exited normally]程序输出
New Result: 30,但我们期望x(10) + y(30)等于40,这说明第二次调用add时,传入的b不是30。 -
重新调试,定位问题 让我们重新运行,这次在第二次调用
add前设置一个条件断点。(gdb) run ... (gdb) # 程序停在第一次 main (gdb) continue ... (gdb) # 程序停在第二次 main这次,我们想在第二次调用
add之前检查y的值,我们可以使用info locals或者直接打印。(gdb) next 12 int result = add(x, y); (gdb) print y $4 = 20 <-- 问题找到了!y 还是 20,没有被赋值为 30通过查看源代码
buggy.cpp,我们发现y = 30;这一行被注释掉了,这就是 Bug 的根源。
高级技巧
- GDB Python API: GDB 可以通过 Python 脚本进行扩展,实现高度定制化的调试功能。
- TUI (Text User Interface):
gdb -tui或在 GDB 内部按Ctrl+XA可以打开一个图形化界面,左侧显示源代码,右侧显示 GDB 终端。 catch命令: 用于捕获特定事件,如catch throw(捕获 C++ 异常抛出)、catch catch(捕获 C++ 异常捕获)。set follow-fork-mode: 调试多进程程序时,决定在fork()之后是跟父进程还是子进程。
这份指南应该能覆盖您日常使用 GDB 的 95% 以上的场景,GDB 是一个非常强大的工具,熟练掌握它将极大地提升您定位和解决复杂 Bug 的能力。
