启动gdb
- 调试可执行文件:gdb
- 调试core文件:gdb
- 调试正在运行的程序:gdb -p
- 指定源文件的路径:gdb ... -d
退出gdb
调试命令
列出源代码:list(l)
列出当前的源代码:l
列出代码时向上走:l -
列出代码时向下走:l +
列出某一行的源代码:l
列出某个函数的源代码:l (注意调试c++程序的时候,必须是file:namespace::classname::func_name)
列出某个区间的源代码:l ,
列出某个内存地址的代码:l <*address>
查看汇编代码:info line & disassemble
查看行/函数的起始终止地址:info line
查看某行的起始终止地址:info line
查看某函数的起始终止地址:info line
列出汇编代码:disassemble
列出当前函数的汇编代码:disassemble
列出某个地址段的汇编代码:disassemble , (start_addr和end_addr就是使用info line指令打印出来的起始终止地址)
列出汇编代码时包含源代码:disassemble /m ,
- 停止点管理:break(断点)/watch(观察点)/catch(捕获点)
设定断点:break(b)
设定文件断点:b
设定函数断点:b (注意调试c++程序的时候,必须是file:namespace::classname::func_name)
设定条件断点:b .... if
设定观察点:watch/rwatch/awatch (注意只有程序开始运行之后才能设定观察点)
表达式的值改变时暂停:watch
表达式被读取时暂停:rwatch
表达式被读取或修改时暂停:awatch
设定捕获点:catch/tcatch (非HP-UNIX只能用于异常,而编码规范又不让我们用异常...了解就好...)
设定捕获点:catch ,event可以是下面表中的值(注意,在非HP-UNIX环境下只有throw/catch有用)
throw catch exception syscall exec fork vfork load unload
tcatch的含义是只捕获一次,并且停住之后自动删除此捕获点
查看停止点:info break / info watch
查看所有停止点(包括break、watch和catch):info break
查看某个停止点:info break
查看所有观察点:info watch
查看某个观察点:info watch
只能使用info break 查看捕获点(catch point)
disable停止点:disable
disable所有停止点:disable
disable某个停止点:disable
disable某个范围内的停止点:disable (range的例子:1-7)
enable停止点:enable
enable所有停止点:enable
enable某个停止点:enable
enable某个范围内的停止点:enable (range的例子:1-7)
删除停止点:delete
删除全部停止点:delete
删除某个停止点:delete
删除某个范围的停止点:delete (range的例子:1-7)
清除停止点:clear
清除当前行停止点:clear
清除指定行停止点:clear
清除指定函数内部所有停止点:clear (注意调试c++程序的时候,必须是file:namespace::classname::func_name)
断点条件修改:condition(只对break有效)
清除断点条件:condition
修改断点条件:condition
断点命令列表:commands
设置断点的命令列表:commands
... command list ...
end
运行程序:run(r)
开始运行:r
带命令行参数执行:r
对正在运行的程序调试:attech & detach
调试正在运行的程序:attach
从正在运行的程序中离开:detach
单步执行进入调用:step(s)
单步执行step-in:s
执行若干步step-in:s
单步执行跳过调用:next(n)
单步执行step-over:n
执行若干步step-over:n
继续执行至下一个断点:continue(c)
继续执行continue:c
继续执行并忽略指定个数个断点:c
继续执行跳出当前循环:until(u)
继续执行跳出当前函数:finish(f)
step-mode设定:
开启step-mode:set step-mode on (让gdb遇到没有debug信息的函数时停止在它的第一行,然后就可以查看它的汇编了)
关闭step-mode:set step-mode off
单步执行机器码:si(stepi)/ni(nexti) (它们的作用与s和n相同)
强制当前函数返回:return
当前函数立即返回:return
当前函数立即以某个返回值返回 :return
强制调用函数:call
强制调用某个函数:call
print命令可以达到同样的目的 :print
跳转执行:jump(j)
跳转到某行:j
跳转到某文件的某行:j
向前向后跳转几行:j +n/-n
跳转到某个地址:j
注意:jump不会修改程序栈中的内容,使用时非常容易引起core,要小心使用
打印变量:print(p)
打印变量:p
打印数组中的前n个变量:p @n
打印其他文件中的变量:p ::
打印其他函数中的变量:p ::
格式化打印:p / xxxx
GDB支持的格式:
x 十六进制
d 十进制
u 无符号十六进制
o 八进制
t 二进制
a 按地址打印(十六进制)
c 字符
f 浮点数
显示变量的类型:ptype
显示变量的类型 :ptype
查看内存:examine(x)
打印地址:x
打印地址并重复n次:x /
按照某种格式打印地址:x /
x 十六进制(默认值)
i 查看汇编代码
s 按照字符串格式打印
按照指定的unit-size打印地址:x /
b 单字节(byte)
h 双字节
w 四字节
g 八字节
/后面的三个参数可以联合起来使用:x /4bx
查看栈信息:
打印栈信息:backtrace(bt)
打印全部栈信息:bt
打印当前frame向上n层:bt <+n>
打印当前frame向下n层:bt <-n>
切换到栈的某一层:frame(f)
打印当前栈信息:f
切换到栈的某一层:f
打印当前栈信息:info frame
沿着栈向上走:up
沿着栈向下走:down
查看线程信息:
打印线程信息:info thread
跳转到某个线程:thread(t)
打印当前线程信息:t
切换到某个线程:t
设定线程运行模式:set scheduler-locking
所有线程都可以执行:set scheduler-locking off
只有当前线程得到执行:set scheduler-locking on
当前线程最高优先级执行:set scheduler-locking step(也就是说除非当前线程交出运行权限(使用finish/util/continue/next命令),否则其他线程都得不到执行)
查看macro信息:
查看macro的定义:info macro
展开macro:macro expand
注意:在编译程序的时候加上gcc的参数-g3
注意:低版本的gdb/gcc组合可能对macro调试的支持不好,需要4x的gcc和7.4及以上的gdb
查看寄存器信息:
查看寄存器的值(不包含浮点寄存器):info registers
查看寄存器的值:info registers
查看某个寄存器的值:info registers
查看所有寄存器的值(包含浮点寄存器):info all-registers
自动显示管理:
设定自动显示:display
打印所有的自动显示:display
设定自动显示变量:display
指定自动显示变量格式:display /
x 十六进制
d 十进制
u 无符号十六进制
o 八进制
t 二进制
a 按地址打印(十六进制)
c 字符
f 浮点数
查看自动显示:info display
enable自动显示:enable display
enable所有的自动显示:enable display
enable某个自动显示:enable display
disable自动显示:disable display
disable所有的自动显示:disable display
disable某个自动显示:disable display
删除自动显示:undisplay / delete display
删除所有的自动显示:undisplay / delete display
删除某个自动显示 :undisplay / delete display
查看信号处理策略:info signals / handle
查看全部信号处理策略:info signals / handle
查看某个信号处理策略:info signals / handle
调整信号处理策略:handle
调整信号处理策略:handle
就是info handle/signals中列出的signal名称
handle支持以下keywords:
nostop 接收到信号不停止,但是打印信息
stop 接收到信号停止程序
print 接收到信号打印信息
noprint 接收到信号不打印信息
pass GDB不响应这个信号
noignore GDB不响应这个信号
nopass GDB响应这个信号
ignore GDB响应这个信号
产生信号量:signal
产生某个信号:signal
命令行参数操作:set args & show args
设定命令行参数:set args
显示命令行参数:show args
运行时动态修改内存中变量的值:set var
使用print命令:print =
使用set var命令:set var =
一些有用的显示设定:
美化数组打印:set print array on
美化结构体打印:set print pretty on
打印union中的数据:set print union on
基于虚函数表打印:set print object on
实用技巧
1.使用gdb 打开core文件
2.之后bt打印栈信息,找到需要查看的位置
3.f 到该位置
4.使用l显示附近的代码,使用p打印需要查看的变量
1.ps aux|grep xxx查找对应程序的pid
2.gdb -p pid或者启动gdb之后attach pid
3.使用info thread查看线程信息,使用t 跳到需要查看的线程
4.之后bt打印栈信息,找到需要查看的位置
5.f 到该位置
6.使用l显示附近的代码,使用p打印需要查看的变量
7.也可以用b设定断点之后再c,等等
8.注意:退出时需要先detach再quit,否则会终止该程序
1.gdb中对stl类型变量的打印支持的不好,所以需要使用内存地址来打印对应的信息
2.首先p ,打印这个对象的内容,比如说一个vector对象
3.然后根据具体打印的信息,找到对应的内存地址
4.根据这个内存地址信息,就可以打印对应的内容了
gdb与vim相似,启动时加载$home目录下的.gdbinit文件,一些显示设定可以直接写在.gdbinit文件中来始终生效
gdb与vim相似,支持用户编写自己的脚本,例如:打印stl容器的gdb脚本,http://www.yolinux.com/TUTORIALS/src/dbinit_stl_views-1.03.txt
本文暂时没有评论,来添加一个吧(●'◡'●)