gdb调试小结

一、启动

1、gdb <program>

当以gdb <program>方式启动gdb后,gdb会在PATH路径和当前目录中搜索<program>的源文件。如要确认gdb是否读到源文件,可使用l或list命令,看看gdb是否能列出源代码。
使用(gdb)r或run命令运行程序。

2、调试在线进程

(1)启动gdb时链接目标进程

在启动gdb的时候,通过参数-p指定目标进程,就可以进入调试状态。刚链接成功后,程序是暂停运行状态,你可以进行设置断点等操作,然后输入(gdb) c 命令继续运行。命令如下:

>gdb -p <PID>:PID是进程ID,可以通过`>ps aux | grep <程序名> `获得。
或者直接 >gdb -p  `pidof <程序名>` 也可以。

(2)gdb中链接目标进程:

 (gdb) attach <PID>

(3)断开链接:

 (gdb) detach

二、信息显示

1、栈信息

不管是操作转储文件还是用gdb设置断点进行调试,都可以输入(gdb)bt打印栈内容进行查看。一般的当机BUG,看下当机的位置,然后看下源代码基本就可以解决了。但是很多情况下简单的(gdb)bt还查不到问题,这时候就要涉及到比较复杂的操作。下面罗列了一些对栈的操作:

(gdb) bt:显示所有栈帧,backtrace。
(gdb) bt 10:显示前面10个栈帧。
(gdb) bt -10:显示后面10个栈帧。
(gdb) bt full:显示栈帧以及局部变量。
(gdb) bt full 10:显示前面10个栈帧以及局部变量。
(gdb) bt full -10:显示后面10个栈帧以及局部变量。
(gdb) frame <栈帧编号>:进入指定的栈帧中,然后可以查看当前栈帧中的局部变量,以及栈帧内容等信息。
(gdb) info frame <栈帧编号>:可以查看指定栈帧的详细信息。
(gdb) up:进入上层栈帧。
(gdb) down:进入下层栈帧。

2、变量

调试BUG过程中查看变量信息是很有帮助的操作,查看方式如下:

 (gdb) p <变量名>
 (gdb) set variable <变量> = <表达式>:将变量的值设定为指定表达式的值。例如 set variable x=10
 (gdb) print <变量> = <表达式>:查看并修改变量

3、寄存器

对于调试来说寄存器中的值也很重要,可以查看到当前正在执行的指令的地址等。具体操作罗列如下:

(gdb) `info reg`:显示所有寄存器。可以简写为:i r。如果要查看具体的寄存器可以这样:`i $ebx`
(gdb) `p $eax`:显示eax寄存器内容。
(gdb) `p/c $eax`:用字符显示eax寄存器内容

反斜杠后面的是显示格式,可使用的格式见下表:该表在显示内存内容的x命令中也是通用的。

格式说明
x显示为十六进制数
d显示为十进制数
u显示为无符号十进制数
o显示为八进制数
t显示为二进制数
a显示为地址
c显示为字符(ASCII)
f显示为浮点小数
s显示为字符串
i显示为机器语言(仅在显示内存的x命令中可用)

4、内存

可以查看具体内存地址中的内容,比如:目前执行的汇编指令,以及栈中内容等。

(gdb) `x $pc`:显示程序指针指向位置的内容。
(gdb) `x/i $pc`:显示程序当前位置的汇编指令。
(gdb) `x/10i $pc`:显示程序当前位置开始往后的10条汇编指令。
(gdb) `disassem $pc`:反汇编当前函数。简写为:`disas $pc`。

5、源代码

(gdb) `list <linenum>`:显示程序第linenum行的周围的源程序。
(gdb) `list <function> `:显示函数名为function的函数的源程序。
(gdb) list :显示当前行后面的源程序。
(gdb) list - :显示当前行前面的源程序。

6、显示格式

(gdb)set print pretty on:如果打开printf pretty这个选项,那么当gdb显示结构体时会比较漂亮。
(gdb)set print array on:打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔。

三、断点

1、设置断点

(gdb) break <函数名>:对当前正在执行的文件中的指定函数设置断点。可简写为:(gdb) b <函数名>
(gdb) break <行号>:对当前正在执行的文件中的特定行设置断点。可简写为:(gdb) b <行号>
(gdb) break <文件名:行号>:对指定文件的指定行设置断点。最常用的设置断点方式。可简写为:(gdb) b <文件名:行号>
(gdb) break <文件名:函数名>:对指定文件的指定函数设置断点。可简写为:(gdb) b <文件名:函数名>
(gdb) break <+/-偏移量>:当前指令行+/-偏移量出设置断点。可简写为:b <+/-偏移量>
(gdb) break <*地址>:指定地址处设置断点。可简写为:b <*地址>
(gdb) tbreak <函数名>:设置临时断点,只生效一次。可简写为:(gdb) tb <函数名>

2、 查看、删除断点

(gdb) info break :显示所有断点以及监视点。可简写为:(gdb) i b
(gdb) delete <编号>:删除编号指向的断点或者监视点。可简写为:(gdb) d <编号>
(gdb) clear <行号>:删除改行的断点。
(gdb) clear <文件名:行号>:删除改行的断点。

3、设置无效、有效断点:

(gdb) disable <断点编号> : 当前断点设置为无效。
(gdb) enable <断点编号>:当前断点设置为有效。

4、条件断点

在调试程序过程中,有时候我们只想在某个条件下停止程序,然后进行单步调试,而条件断点就是为此而设计。下面是条件断点的操作方式:

(gdb) b <断点> if <条件表达式> : 例如:b main.cpp:8 if x=10 && y=10
(gdb) condition <断点编号>:删除该断点的条件。
(gdb) condition <断点编号> <条件表达式>:修改断点条件。例如:condition 1 x=10 && y=10

5、监视点

可以监视某个变量,在变量被访问或者被修改时程序会在当前点进入断点。删除,查看监视点的方式与断点相同。设置监视点方式如下:

(gdb) watch <表达式>:表达式发生变化时暂停。
(gdb) awatch <表达式>:表达式访问或者改变时暂停。
(gdb) rwatch <表达式>:表达式被访问时暂停。
(gdb) info watchpoints:列出当前所设置的所有观察点。

6、断点命令

每次断点发生时候,想要查看的变量很多时,如果每个变量都手动print则需要浪费很多时间。断点命令可以在断点发生时批量执行gdb命令。下面是断点命令的设置方式:

(gdb) commands <断点编号>
(gdb) >print x
(gdb) >print y
(gdb) >end

首先输入gdb命令commands <断点编号>然后回车,这时候会出现>提示符。出现>提示符后可以输入断点发生时需要执行的gdb命令,每行一条,全部输入完成后输入end结束断点命令。

四、其他

1、强制函数返回

如果你的调试断点在某个函数中,并还有语句没有执行完。你可以使用return命令强制函数忽略还没有执行的语句并返回。

return
return <expression>

使用return命令取消当前函数的执行,并立即返回,如果指定了,那么该表达式的值会被认作函数的返回值。

2、强制调用函数

call <expr>

表达式中可以一是函数,以此达到强制调用函数的目的。并显示函数的返回值,如果函数返回值是void,那么就不显示。

另一个相似的命令也可以完成这一功能——print,print后面可以跟表达式,所以也可以用他来调用函数,print和call的不同是,如果函数返回void,call则不显示,print则显示函数返回值,并把该值存入历史数据中。

参考

100个gdb小技巧
gdb调试器使用总结
陈皓-用gdb调试程序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值