gdb调试记录
背景
gdb调试C/C++程序
一般来说,windows下可以用visual studio就有很强大的代码调试工具,而在linux下,一般使用的gdb进行调试,这里做一个记录。
参考链接
常用操作
以下以调试wx_app这个本地程序为例,这个程序是已经编译生成好的执行程序。
1.启动GDB
gdb 执行程序
注意,该指令在启动 GDB 的同时,会打印出一堆免责条款。通过添加 –silent(或者 -q、–quiet)选项,可将比部分信息屏蔽掉
2.查看代码,运行程序
l指令 查看代码列表
r指令 开始运行程序
3.设置普通断点
b指令 设置断点
格式
b 函数名称
命中断点
n 执行下一条语句
c 继续运行程序
4.设置断点常用的语法格式有以下2种
1、(gdb) break location // b location
在这个格式中,location 用于指定打断点的具体位置,其表示方式有多种,如表 1 所示。
示例如下:
设置断点如下
p指令 查看指定变量当前的值
命中断点如下
2、(gdb) break … if cond // b .. if cond
在这个格式中,… 可以是表 1 中所有参数的值,用于指定打断点的具体位置;cond 为某个表达式。整体的含义为:每次程序执行到 … 位置时都计算 cond 的值,如果为 True,则程序在该位置暂停;反之,程序继续执行。
5.设置观察断点
GDB 调试器支持在程序中打 3 种断点,分别为普通断点、观察断点和捕捉断点。其中 break 命令打的就是普通断点,而 watch 命令打的为观察断点。使用 catch 命令建立捕捉断点。
借助观察断点可以监控程序中某个变量或者表达式的值,只要发生改变,程序就会停止执行。相比普通断点,观察断点不需要我们预测变量(表达式)值发生改变的具体位置。
对于监控 C、C++ 程序中某变量或表达式的值是否发生改变,watch 命令的语法非常简单,如下所示:
(gdb) watch cond
其中,conde 指的就是要监控的变量或表达式。
和 watch 命令功能相似的,还有 rwatch 和 awatch 命令。其中:
rwatch 命令:只要程序中出现读取目标变量(表达式)的值的操作,程序就会停止运行;
awatch 命令:只要程序中出现读取目标变量(表达式)的值或者改变值的操作,程序就会停止运行。
强调一下,watch 命令的功能是:只有当被监控变量(表达式)的值发生改变,程序才会停止运行。
如果我们想查看当前建立的观察点的数量,借助如下指令即可:
(gdb) info watchpoints
值得一提的是,对于使用 watch(rwatch、awatch)命令监控 C、C++ 程序中变量或者表达式的值,有以下几点需要注意:
1、当监控的变量(表达式)为局部变量(表达式)时,一旦局部变量(表达式)失效,则监控操作也随即失效;
2、如果监控的是一个指针变量(例如 *p),则 watch *p 和 watch p 是有区别的,前者监控的是 p 所指数据的变化情况,而后者监控的是 p 指针本身有没有改变指向;
3、这 3 个监控命令还可以用于监控数组中元素值的变化情况,例如对于 a[10] 这个数组,watch a 表示只要 a 数组中存储的数据发生改变,程序就会停止执行。
6.建立捕捉断点
和前 2 种断点不同,普通断点作用于程序中的某一行,当程序运行至此行时停止执行,观察断点作用于某一变量或表达式,当该变量(表达式)的值发生改变时,程序暂停。而捕捉断点的作用是,监控程序中某一事件的发生,例如程序发生某种异常时、某一动态库被加载时等等,一旦目标时间发生,则程序停止执行。
用捕捉断点监控某一事件的发生,等同于在程序中该事件发生的位置打普通断点。
建立捕捉断点的方式很简单,就是使用 catch 命令,其基本格式为:
(gdb) catch event
其中,event 参数表示要监控的具体事件。对于使用 GDB 调试 C、C++ 程序,常用的 event 事件类型如表 1 所示。
常用指令
一般比较常用的调试指令如下
还有遇到core dump的时候,输入
(gdb)bt
可以查看段错误崩溃在哪里
其他指令
虽然不常用,但是偶尔也很有用,不再举例
(1)tbreak命令
tbreak 命令可以看到是 break 命令的另一个版本,tbreak 和 break 命令的用法和功能都非常相似,唯一的不同在于,使用 tbreak 命令打的断点仅会作用 1 次,即使程序暂停之后,该断点就会自动消失。
tbreak 命令的使用格式和 break 完全相同,有以下 2 种:
1、(gdb) tbreak location
2、(gdb) tbreak … if cond
其中,location、… 和 cond 的含义都和 break 命令中的参数含义相同,即表 1 也同样适用于 tbreak 命令。
(2)rbreak命令
rbreak命令的使用语法格式为:
(gdb) rbreak regex
其中 regex 为一个正则表达式,程序中函数的函数名只要满足 regex 条件,rbreak 命令就会其内部的开头位置打断点。值得一提的是,rbreak 命令打的断点和 break 命令打断点的效果是一样的,会一直存在,不会自动消失。
如下,通过执行rbreak rb_指令,找到了程序中所有以 rb_ 开头的函数,并在这些函数内部的开头位置打上了断点