近段时间在测试程序的时候,遇到了许多问题,又需要再次用到gdb,虽然之前也写过一篇关于gdb调试的文章,但是涵盖的内容比较片面,有许多实用的gdb命令和操作都没有介绍到,于是又写了这篇文章来丰富加强一下自己的gdb技能。
1.GDB启动方法
1. gdb + 可执行文件
事先将源代码编译生成可执行文件,输入gdb + 可执行文件的名字进入调试状态,如:
gdb test
gdb ./test
2. gdb + 进程id
想要调试已经运行的进程,通过
ps aux | grep XXX
命令(XXX表示要搜索的程序名称)查找进程id,然后输入gdb -p + id号进入调试状态:
# 随便举个例子,假设我们要调试的pid为11654
gdb -p 11654
3. gdb + coredump文件
在Linux下执行程序发生段错误等导致程序崩溃时,内核会生成一个coredump文件,用gdb打开coredump文件来定位发生异常的原因。这里假设我们在执行程序test的时候,生成coredump文件core_test-4907-1667541568,输入以下命令进入调试状态
gdb test core_test-4907-1667541568
关于调试coredump文件,今天我在练习的过程中还遇到过一个问题,就是在程序崩溃的时候,并没有生成coredump文件,原因是我的coredump文件的大小被默认设置为0了,通过ulimit -c命令可以查看coredump文件的大小,通过ulimit -a 查看shell对所有文件的限制。
输入以下指令将coredump文件大小限制放开
ulimit -c unlimited
如果这样操作以后还是无法生成coredump文件,可以参考这篇文章
【Linux】生成coredump文件方法记录
。
2.GDB指令
2.1 r (run)
输入r(run)指令运行程序,每次输入r的时候,都会从新执行一遍程序,如果有断点,会在运行到断点位置暂停。
2.2 q (quit)
输入q(quit)退出gdb调试
2.3 l (list)
输入l(list) 显示10行代码,想看指定行号的代码可以输入以下指令:
#显示第n到第m行代码
l n,m
#显示n-5到n+4行代码
l n
#显示文件test.cc中第n到第m行代码
l test.cc:n,m
2.4 p (print)
输入p (print) 打印变量的值:
# 打印变量var的值
p var
# 打印变量var的地址
p &var
# 按照特殊形式打印var的值
p /t var #按照二进制打印var的值
p /o var #按照八进制打印var的值
p /d var #按照有符号十进制打印var的值
p /u var #按照无符号十进制打印var的值
p /c var #按照字符类型打印var的值
p /x var #按照十六进制类型打印var的值
2.5 info
输入info查看各种信息,关于info的功能十分强大,具体使用方法可以使用help info来查看
2.6 b (break)
输入b(break)进行打断点操作:
# 在func函数处加断点
b func
# 在第n行处加断点
b n
# 在文件test.cc的n行处加断点
b test.cc:n
# 当满足某个条件时,加断点,例(当 i == n 时,在 m 行加断点)
b m if i == n
当gdb运行到断点处,想要继续执行程序,别忘了输入c而不是r,c是继续执行程序,r是从头执行程序。
2.7 del (delete)
输入del命令可以将当前设置过的断点删除,可以先通过info breakpoints 查看当前断点有哪些,然后可以根据编号进行断点删除,如果不指定编号的话,会删除所有所有断点。
2.8 n (next)
单步执行代码,不进入到函数内部
2.9 s (step)
单步执行代码,会进入到函数内部