gdb调试
基本命令
要想使用gdb调试,在编译的时候必须添加-g参数,产生调试信息
# gcc -g debugme.c -o debugme
导入调试代码
- 可以在使用gdb调试时添加参数 gdb a.out
- 也可以在进入gdb后使用file命令导入调试文件,(gdb)> file a.out
运行:run
run后面可以添加调用参数,或者直接用 set args 进行设置
查看代码:
list n1,n2 列出n1到n2之间的代码
list 不跟参数列出当前的十行代码
查看变量值:
print var
查看数组:
当查看一段连续内存是时,使用@运算符
如果是静态数组可以直接在p后面加数组名;如果是动态数组,要用 *arrName@len的形式
查看调用栈:
backtrace
frame 可以查看到当前代码
设置断点:
break linenum
break funcname
设置满足一定条件的断点:
break linenum if expr
break funcname if expr
查看断点情况: info break
删除断点:
基于断点号删除断点:
delete : 删除所有断点
delete breaknum : 删除标号为breaknum的断点
delete breaknum1,breaknum2 : 删除标号在breaknum1到breaknum2之间的所有断点
基于行号删除断点:
clear location : 删除当前行的所有断点
clear funcname :删除funcname函数的所有断点
clear linenum : 删除linenum行的所有断点
执行:
单步调试: step, next
两者的区别是,当又函数的时候,step将跟入函数内部;next会跳过函数
continue到下一个断点
终止
跳出函数: finish
终止: q
跳出循环: until
回到过去
跟踪调试程序的过程中,偶尔会错过一些关键点,不得不重新启动程序。如果错过的这些关键点不容易再现,就更令人懊恼了。GDB提供一种机制可以让你将程序向后调整,重新来过。这种机制叫做checkpoint,你可以在程序运行的关键点处执行checkpoint命令,你将得到一个数字(check-num)来标识这个checkpoint。在以后的某个时刻使用restart check-num将程序回滚到设置该checkpoint的时刻,而此时此刻的“内存状态”恰如彼时彼刻,你可以重新调试这段程序(比如设置不同的变量值来测试不同的情况)。但覆水难收的道理你是懂得,回滚的这段程序之间产生的内存之外的效应是无法恢复的,比如写出到文件的数据收不回来了(但文件的指针偏移是可以恢复的,因为它的值保存在内存),通过网络发出的数据就更要不回来了。
使用i checkpoints可以查看checkpoint信息,比如check-num及其所处代码行。
据我揣测,GDB的这种“回到过去”的伎俩并不是逐步撤销之前运行的指令,而是在checkpoint命令执行的时候,把被调试程序fork/clone了
要想查看宏展开
默认使用 -g 编译的时候是查看不到宏定义的,不过可以使用 -g3(就行优化等级 -o3一样)这样就可以查看宏展开内容了
macro expand MAX(x,y)
macro exp MAX(x,y)
查看栈中内容:
backtrace 可以查看当前栈层次结构
查看指定地址的内容:
x/[n][f][u]
n是要显示的内存单元的个数
f:显示格式
x(hex) 按十六进制格式显示变量。
d(decimal) 按十进制格式显示变量。
u(unsigned decimal) 按十进制格式显示无符号整型。
o(octal) 按八进制格式显示变量。
t(binary) 按二进制格式显示变量。
a(address) 按十六进制格式显示变量。
c(char) 按字符格式显示变量。
f(float) 按浮点数格式显示变量
i(instruction) 显示命令
u:每个单元的大小,按字节数来计算。默认是4 bytes。GDB会从指定内存地址开始读取指定字节,并把其当作一个值取出来,并使用格式f来显示
b:1 byte h:2 bytes w:4 bytes g:8 bytes
查看当前程序栈的内容: x/10x $sp-->打印stack的前10个元素
查看当前程序栈的信息: info frame----list general info about the frame
查看当前程序栈的参数: info args---lists arguments to the function
查看当前程序栈的局部变量: info locals---list variables stored in the frame
查看当前寄存器的值:info registers(不包括浮点寄存器) info all-registers(包括浮点寄存器)
查看当前栈帧中的异常处理器:info catch(exception handlers)
查看变量的类型:
* whatis :显示某个变量或表达式的数据类型。使用格式:
whatis 变量或表达式
* ptype :和whatis类似,用于显示数据类型,但是它还可以显示typedef定义的类型等。使用格式:
ptype 变量或表达式