本笔记基于Marc Haisenko (marc@darkdust.net )于2007年制作的GDB速查表整理而成。
同时包含了在学习课程cs300时的一些体悟,也许可以算一篇学习笔记?
本来应该在一年前写完的,没想到拖着拖着拖到现在了。果然博客只有在刚刚建完的时候才有最大的热情去写。
调试能力是编程过程中不可或缺的技能。固然,如今的许多IDE已经将调试简单化了,但是在某些场景,特别是命令行环境下,传统的调试工具仍然有其使用价值。GDB(GNU Debugger)便是如此。
为什么需要GDB?
在开发C/C++程序时,我们经常会遇到程序崩溃、逻辑错误等问题。虽然printf大法好用,但在复杂程序中,它显得力不从心。GDB作为GNU项目下的标准调试器,能让我们:
在程序崩溃时查看状态
设置断点精确控制执行流程
检查变量和内存内容
跟踪函数调用栈
甚至修改程序运行时状态
是的,这些功能现代的IDE都能够做到。但在CLI环境下,GDB无疑是更优雅的选择。谁没有过All In Terminal
的梦想?与此同时,更加直接和传统的使用方式也让它有利于促进语言的学习。C/C++
的特性在GDB下得以很好的展现。这或许也是众多著名cs公开课青睐它的原因之一。
启动
1 2 3 gdb <program> [core dump] gdb --args <program> <args...> gdb --pid <pid>
运行控制 :
1 2 3 set args <args...> # 设置程序参数 run # 运行程序 kill # 终止运行中的程序
断点管理
1 2 3 4 5 break <where> # 设置断点 delete <breakpoint#> # 删除断点 clear # 删除所有断点 enable <breakpoint#> # 启用断点 disable <breakpoint#> # 禁用断点
断点位置 :
function_name
- 函数名
line_number
- 当前源文件行号
file:line_number
- 指定文件的行号
观察点
1 2 watch <where> # 设置观察点 delete/enable/disable <watchpoint#> # 管理观察点
条件断点
1 2 break/watch <where> if <condition> # 条件触发 condition <breakpoint#> <condition> # 修改现有条件
堆栈检查
1 2 3 backtrace # 显示调用栈 (或 where) backtrace full # 显示调用栈及局部变量 frame <frame#> # 选择操作的栈帧
单步执行
1 2 3 4 step # 执行下一行(进入函数) next # 执行下一行(不进入函数) finish # 继续执行直到当前函数返回 continue # 继续正常执行
变量与内存
1 2 3 4 print/format <what> # 打印变量/内存 display/format <what> # 每次单步后自动打印 undisplay <display#> # 移除display x/nfu <address> # 打印内存
内存打印格式 :
n
: 打印单元数(默认1)
f
: 格式字符
u
: 单元大小(b
=字节, h
=半字, w
=字, g
=巨字)
格式字符 :
a
: 指针
c
: 字符
d
: 有符号十进制
f
: 浮点数
o
: 八进制
s
: C字符串
t
: 二进制
u
: 无符号十进制
x
: 十六进制
变量表示 :
expression
: 任意C表达式
file_name::variable_name
: 静态变量
function::variable_name
: 函数内变量
{type}address
: 指定类型的内存地址
$register
: 寄存器内容($esp
, $ebp
, $eip
)
线程操作
1 thread <thread#> # 选择操作的线程
程序操作
1 2 set var <variable_name>=<value> # 修改变量值 return <expression> # 强制函数立即返回
源代码管理
1 2 3 4 5 directory <directory> # 添加源文件搜索目录 list # 显示源代码 list <filename>:<function> # 显示特定函数 list <filename>:<line> # 显示特定行 set listsize <count> # 设置list显示行数
信号处理
1 2 handle <signal> <options> # 信号处理设置 # options: (no)print, (no)stop, (no)pass
信息查询
1 2 3 4 5 6 7 8 9 10 11 disassemble [<where>] # 反汇编 info args # 当前函数参数 info breakpoints # 断点信息 info display # display信息 info locals # 局部变量 info sharedlibrary # 已加载共享库 info signals # 信号处理信息 info threads # 线程列表 show directories # 源文件搜索目录 show listsize # list显示行数 whatis <variable_name> # 变量类型
技巧
Core dump定位 :gdb program core
精确定位崩溃点
动态调试 :运行中附加进程 gdb --pid $(pgrep -n myapp)
内存快照 :x/16xb &myvar
查看变量内存布局
绕过函数 :finish
+ return 0
快速跳过有问题的函数
自动显示 :display/x $eax
每次停顿时自动显示寄存器
其他技巧 :
使用display
自动监控关键变量
条件断点break if
避免频繁中断
x/10xw $esp
快速查看栈内容
finish
快速跳出当前函数
return
修改函数返回值进行测试
命令速查表
类别
命令
用途
执行
run
启动程序
断点
b main
在main函数设置断点
检查
p var
打印变量值
内存
x/4xw $esp
查看栈顶4字
栈
bt
显示调用栈
线程
thread 2
切换到线程2
修改
set var i=10
修改变量值