前情提要:
断点
观察点
观察点是一个特殊的断点,当表达式的值发生变化时,它将中断下来。表达式可以是一个变量的值,也可以包含由运算符组合的一个或多个变量的值。观察点有时也被称为数据断点(vc中) 。
gdb中观察点分为hardware watchpoint和software watchpoint。它们分别由硬件和软件生成,hardware watchpoint不会对程序有任何影响,而software watchpoint会降低程序的运行效率。在gdb中设置的都是软件观察点。
观察点的主要作用是定位堆上的数据何时被修改。
命令 | 功能 |
---|---|
watch <expression> <thread id> | 为表达式设置写断点,当变量被目标线程写入时会击中断点。当不指明线程时,默认为所有线程设置观察点,下同。 |
rewatch <expression> <thread id> | 为表达式设置读断点,当变量被目标线程读取时会击中断点 |
awatch <expression> <thread id> | 为表达式设置读写断点,当变量被目标线程读取或写入时会击中断点 |
info watch | 查看所有观察点 |
delete/disable/enable <id> | 删除/禁用/启用观察点 |
值得注意的是当监控变量为局部变量时,一旦局部变量失效,数据断点也会失效;且如果监控的是指针变量p,则watch *p监控的是p所指内存数据的变化情况,而watch p监控的是p指针本身有没有改变指向。
这就有一个问题了,观察点主要是观察堆上的数据,但定位到堆资源的指针一般是局部变量,所以为了解决观察点失效的问题,就有以下两种解决方法:
方法 | 命令 | 功能 |
---|---|---|
1 | p &<varaiable> | 查看变量的内存地址 |
watch *(<type> *) <address> | 通过内存地址间接设置断点 | |
2 | watch -I <variable> | 指定location参数 |
watch <variable> thread <id> | 仅编号为id的线程修改变量variable值时会中断 |
捕获点
捕获点是一个特殊的断点,当捕获到某个事件时就会中断下来。
命令 | 功能 |
---|---|
catch <event> | 设置捕获某个事件的捕获点 |
补充命令
命令 | 功能 |
---|---|
commands <id> <cmd> end | 为断点执行命令,cmd可以是多行命令,只要不输入end就算入其中,类似于MySQL的事务。 如果不指定某一个断点,就默认为最后一个断点。 |
save breakpoints <file> | 保留断点信息到文件,适用于需要临时调试其他文件,但不能丢弃当前条件文件断点的情况。 |
source <file> | 从文件中读取断点信息。因为文件中存储的就是设置断点的指令,类似于MySQL的备份,所以自己在文件中添加的断点指令也能够读取出来。 |
文本用户界面(TUI模式)
命令 | 功能 |
---|---|
gdb <exe> -tui | 在启动gdb时就启动tui模式 |
layout src / asm / reg | 显示源码 / 汇编 / 寄存器窗口,可以用于从命令行模式转成tui模式 |
layout split | 切分窗口。最多有3个窗口,其中必有命令窗口,剩下两个窗口在源码 / 汇编 / 寄存器之间显示 |
focus cmd / src / asm / reg | 将焦点切换到对应窗口,具有焦点的界面可以通过上下按键来移动 |
focus(fs) next(n)/ prev(p) | 切换到当前焦点的下一个 / 上一个界面 |
info win | 查看当前拥有焦点的窗口 |
Ctrl + n / p | 下 / 上 一条命令,如果焦点在cmd窗口,可以直接通过↑↓按键来操控 |
Ctrl + x + a | 关闭界面模式 |
源码界面行号旁边显示的b是还未击中的断点,B是已经击中过1次及以上的断点,h为硬件断点;断点旁的+号代表该断点是可用的。
查看变量类型
命令 | 功能 |
---|---|
whatis <variable / type> | 单纯查看变量的类型 |
ptype [<option>] <varibale / type> | 显示类型的定义如成员变量、成员函数、类型重定义(只有使用了的类型重定义才会显示出来) |
option为 /m | 不显示成员函数 |
option为 /t | 不显示类型重定义 |
option为 /o | 显示类和结构体的内存对齐状态 |
set print object on | 显示对象真实的类型,用于显示多态的接收类型 |
i variable <regex> | 查看变量的定义位置,只支持全局变量和静态变量 |
线程管理
命令 | 功能 |
---|---|
info / i threads | 查看所有线程信息,线程id前的 * 号代表当前线程 |
thread <id> | 切换线程 |
thread find <regex> | 通过正则表达式匹配来查找线程,查找的材料可以是线程的名字、LWP、地址 |
thread name <name> | 为当前线程设置名字 |
b <local> thread <id> | 为特定线程设置断点,如果是直接设置断点,如b 6,那么所有线程都会在第6行停下来 |
thread apply <id ... > [<option>)]<gdb cmd> | 为线程执行命令,当id栏为all时,为所有线程执行命令 |
当option为 -s 时 | 不显示gdb命令的错误信息,如使用不存在的gdb命令就不会提示错误 |
当option为 -q 时 | 将多个线程执行任务的结果打印在一起,不用线程id做划分 |
set print thread-events on / off | 开启 / 关闭打印线程事件信息 |
show print thread-event | 显示当前打印线程事件信息状态 |
设置线程锁
命令 | 功能 |
---|---|
set scheduler-locking off | 不锁定线程,会有线程切换 |
set scheduler-locking on | 锁定线程,只有当前或指定线程可以运行 |
set scheduler-locking step | 当单步执行某一线程时,其他线程不会执行,同时保证在调试过程中当前线程不会发生改变。但如果在该模式下执行 continue、until、finish 命令,则其他线程也会执行 |
show scheduler-locking | 查看线程锁定状态 |
执行命令及结果输出
命令 | 功能 |
---|---|
shell / ! <bash cmd> | 调用bash命令 |
pipe / | <cmd> | <cmd> | 通过管道对命令的结果进行再处理,在管道后面执行bash命令不需要加bash或! |
set logging on / off | 启用 / 关闭将gdb中的打印信息全部储存到文件中 |
set logging file <filename> | 设置输出文件,如果没有设置输出文件就会默认输出当当前目录的gdb.txt中 |
set logging overwrite | 将输出模式设置为覆盖,默认输出模式为追加 |