GDB调试工具
1. 开发人员必备的四个Linux工具
|----------|------------------|------|
| 工具 | 用途 | 重要性 |
| gcc | 编译器,将源文件转换为可执行程序 | 必须掌握 |
| vim | Linux下的文本编辑器 | 必须掌握 |
| gdb | 调试器,检查程序的逻辑错误 | 必须掌握 |
| makefile | 工程管理工具 | 必须掌握 |
2. 启动和配置GDB
编译时添加调试信息
# 编译时加入 -g 选项,生成调试信息
gcc -g 1.c -o myprogram
启动GDB
# 启动调试器
gdb ./myprogram
# 或直接调试程序
gdb --args ./myprogram arg1 arg2
3. 常用GDB命令速查表
|------------|----|-------------------|-----------------------|
| 命令 | 简写 | 功能描述 | 示例 |
| break | b | 设置断点 | b 14, b fun, b 1.c:16 |
| next | n | 单步执行(不进入函数) | n |
| step | s | 单步执行(进入函数) | s |
| print | p | 显示变量值 | p a, p *ptr |
| display | | 持续显示变量值 | display a |
| continue | c | 继续运行到下一个断点 | c |
| return | | 强制从当前函数返回 | return |
| where/bt | | 查看调用栈(逆序) | where, bt |
| list | l | 显示源代码 | l, l 10quit |
| q | q | 退出GDB | q |
| run | r | 运行程序 | r, r arg1 arg2 |
| layout src | | 显示源码界面 layout src | layout src |
4. 标准调试流程
步骤1-2:准备和启动
# 1. 编译时加入调试信息
gcc -g source.c -o program
# 2. 启动GDB
gdb ./program
步骤3-4:设置断点和运行
# 在GDB中设置断点
(gdb) b 16 # 在当前文件的第16行设置断点
(gdb) b main # 在main函数入口设置断点
(gdb) b source.c:36 # 在指定文件的第36行设置断点
(gdb) b function_name # 在指定函数设置断点
# 运行程序
(gdb) r # 无参数运行
(gdb) r arg1 arg2 # 带命令行参数运行
步骤5-7:调试循环
(gdb) n # 单步执行(跳过函数)
(gdb) s # 单步执行(进入函数)
(gdb) p variable # 查看变量值
(gdb) display variable # 持续监控变量
(gdb) c # 继续执行到下一个断点
5. 段错误调试专门流程
段错误调试步骤
编译带调试信息
gcc -g problematic.c -o program
启动GDB
gdb ./program
运行程序(不需要设置断点)
(gdb) r
重现错误
如果程序需要输入,在此时提供输入
等待段错误发生
分析错误
(gdb) where # 查看调用栈,显示错误位置
(gdb) bt # 同where,显示回溯信息
# 查看相关变量
(gdb) p variable
(gdb) p *pointer
6. 实用技巧
源码界面模式
(gdb) layout src # 开启源码界面,同时显示代码和调试信息
(gdb) layout split # 分屏显示源码和汇编
(gdb) Ctrl + X + A # 切换源码/终端模式
断点管理
(gdb) info breakpoints # 查看所有断点
(gdb) delete breakpoint 1 # 删除1号断点
(gdb) disable breakpoint 2 # 禁用2号断点
(gdb) enable breakpoint 2 # 启用2号断点
监视点(观察变量变化)
(gdb) watch variable # 当变量变化时暂停
(gdb) watch *(int*)0x12345678 # 监视内存地址
多线程调试
(gdb) info threads # 查看所有线程
(gdb) thread 2 # 切换到线程2
(gdb) thread apply all bt # 查看所有线程的堆栈
7. 实际调试示例
示例1:常规调试
# 编译
gcc -g test.c -o test
# 调试
gdb ./test
(gdb) b main
(gdb) r
(gdb) n # 逐步执行
(gdb) p x # 查看变量x
(gdb) c # 继续执行
示例2:段错误调试
# 编译
gcc -g segfault.c -o segfault
# 调试
gdb ./segfault
(gdb) r # 运行程序,等待段错误
(gdb) where # 查看错误位置
输出示例:
#0 0x0000000000400566 in function_name (ptr=0x0) at segfault.c:71
分析:ptr为空指针,在第71行解引用导致段错误
8. 配置和优化
~/.gdbinit 配置文件
# 开启tui模式
set tui enable
# 设置反汇编风格
set disassembly-flavor intel
# 设置打印选项
set print pretty on
set print array on
# 自定义命令
define mybt
bt full
info registers
7.提高调试效率的技巧
-
使用标签:在关键代码处设置标签(如:// TODO: check)
-
条件断点:b 25 if i == 100 当i=100时在第25行暂停
-
命令自动化:为断点关联命令序列