GDB调试 Memo
GDB调试 Memo
核心概述
GDB是GNU开源调试器,与GCC配套,支持多语言(C/C++/Ada等)、多系统,为字符界面操作。核心功能:程序启停控制、断点管理、代码查看、变量监控、单步调试等。
吉祥物:射手鱼(Archer Fish),寓意“精准捕杀bug”。
一、调试准备(关键前提)
编译程序时必须添加调试选项,否则无法使用GDB调试。
- 核心选项:-g(在可执行文件中嵌入源代码关联信息,不嵌入完整源文件,调试时需保证源文件可访问)
- 推荐可选选项:
-O0:关闭编译器优化,避免代码执行逻辑与源码不一致-Wall:开启所有警告,提前规避潜在bug
- 编译示例:
1 | # C程序编译 |
注意:带-g的可执行文件体积会略大(如示例中app 9816字节 vs 无-g的app1 8608字节)。
二、GDB启停与参数设置
2.1 启动GDB
- 命令格式:gdb 可执行程序名
- 示例:
1 | gdb app # 启动GDB并关联app程序,此时程序未执行 |
2.2 给程序传命令行参数
适用场景:调试需要命令行参数的程序(如main(int argc, char* argv[])),需在程序启动前设置。
- 核心命令:
- 设置参数:
set args 参数1 参数2 ... - 查看参数:
show args
- 示例:
1 | (gdb) set args 11 22 33 44 55 # 给app设置命令行参数11-55 |
2.3 启动被调试程序
调试中仅能启动一次,两种启动方式:
run(缩写r):无断点则执行完程序;有断点则停在第一个断点start:停在main函数第一行,等待后续调试命令
- 后续继续运行:continue(缩写c),从当前阻塞位置继续,直到下一个有效断点
- 示例:
1 | (gdb) start # 启动程序,停在main第一行 |
2.4 退出GDB
- 命令:quit(缩写q)
- 示例:(gdb) q # 终止GDB进程,退出调试
三、代码查看命令(list/l)
无可视化界面时,通过命令查看源码,辅助定位断点位置。命令:list(缩写l),默认一次显示10行。
3.1 查看当前文件(默认main函数所在文件)
1 | (gdb) l # 从第一行开始显示 |
3.2 切换并查看其他文件
- 命令格式:l 文件名:行号 或 l 文件名:函数名
- 示例:
1 | (gdb) l insert.cpp:8 # 切换到insert.cpp,显示第8行附近代码 |
3.3 调整显示行数
1 | (gdb) set listsize 20 # 设置一次显示20行 |
四、断点操作(核心调试功能)
断点命令:break(缩写b),用于让程序在指定位置阻塞,便于观察状态。
4.1 设置断点
- 普通断点(当前文件):
1 | (gdb) b 12 # 在当前文件第12行设断点 |
- 普通断点(非当前文件):
1 | (gdb) b test.cpp:16 # 在test.cpp第16行设断点 |
- 条件断点(仅满足条件时阻塞,常用于循环):
1 | (gdb) b 20 if i==10 # 第20行设断点,仅当变量i等于10时生效 |
4.2 查看断点信息
- 命令:info break(缩写i b)
- 示例及字段说明:
1 | (gdb) i b |
4.3 删除断点
- 命令:delete(缩写del/d)+ 断点编号/区间
- 示例:
1 | (gdb) d 1 # 删除编号1的断点 |
4.4 切换断点状态(启用/禁用)
临时不用的断点无需删除,可设置为禁用状态。
- 禁用断点:
disable(缩写dis)+ 编号/区间 - 启用断点:
enable(缩写ena)+ 编号/区间
- 示例:
1 | (gdb) dis 2 4 # 禁用编号2、4的断点 |
五、核心调试命令(程序阻塞后使用)
5.1 变量查看与打印
5.1.1 手动打印变量值(print/p)
- 命令:print(缩写p),支持格式化输出。
- 格式化字符表:
| 格式化字符(/fmt) | 说明 |
|---|---|
| /x | 十六进制(整数) |
| /d | 有符号十进制(整数) |
| /u | 无符号十进制(整数) |
| /o | 八进制(整数) |
| /t | 二进制(整数) |
| /f | 浮点数格式 |
| /c | 字符格式 |
- 示例:
1 | (gdb) p i # 十进制打印变量i |
5.1.2 查看变量类型(ptype)
- 命令:ptype 变量名
- 示例:
1 | (gdb) ptype i # 查看变量i的类型 |
5.1.3 自动打印变量(display)
区别于print:程序每次暂停(如单步、断点)时自动打印,适合跟踪变量变化。
- 设置自动打印:
display 变量名或display/fmt 变量名 - 查看自动打印列表:
info display(缩写i display) - 取消自动打印:
undisplay 编号或delete display 编号 - 禁用/启用自动打印:
disable display 编号/enable display 编号
- 示例:
1 | (gdb) display i # 自动打印变量i |
5.2 单步调试
程序阻塞后,逐行/逐函数调试,观察执行流程。
step(缩写s):逐行执行,会进入函数体内部next(缩写n):逐行执行,不进入函数体内部(函数整体执行)finish:从当前函数体内部跳出(需确保函数内无有效断点)until:直接跳出循环体(条件:循环内无有效断点,需在循环开始/结束行执行)
- 示例:
1 | (gdb) s # 单步执行,进入函数 |
5.3 手动设置变量值
适用场景:快速让变量达到目标值(如循环因子、特殊条件值),提高调试效率。
- 命令:set var 变量名=目标值
- 示例:
1 | (gdb) set var i=90 # 直接将变量i设为90 |
六、高频命令速查表
| 功能 | 完整命令 | 缩写 | 核心用法 |
|---|---|---|---|
| 启动GDB | gdb 可执行程序 | - | gdb app |
| 启动程序 | run | r | r(停在第一个断点) |
| 启动停main函数 | start | - | start |
| 继续运行 | continue | c | c(到下一个断点) |
| 设断点 | break | b | b 12、b main、b test.cpp:8 |
| 查看断点 | info break | i b | i b(查编号、状态) |
| 删除断点 | delete | d | d 1、d 2-5 |
| 单步(进函数) | step | s | s |
| 单步(不进函数) | next | n | n |
| 打印变量 | p | p i、p/x i | |
| 查看代码 | list | l | l、l 15、l test.cpp:main |
| 退出GDB | quit | q | q |