gdb查coredump问题流水账
1,前言
如果c++发生了coredump,该怎么办。写c++项目很是头疼的是碰到c++的coredump,程序终止的时候留的信息很有限,不知道怎么查找问题。
2,GDB介绍
一直想了解GDB是怎么使用的却没怎么深入了解,只是简单熟悉了gdb的简单使用命令,比如辅助来打断点,熟悉代码调用栈的作用。
(1),gdb启动调试
如果需要调试可执行文件,gdb exefilename.out 进入调试模式来跑,静态方式。
如果需要对某个正在运行中的进程进行调试,则 gdb -p pid,或者 gdb attach pid 的方式
(2),gdb设置断点
break(b) linenum 是 针对当前文件的第几行进行断点,如果多个文件要到其他文件下断点,使用 b filename:linenum 则是到指定文件名下断点
break(b) function; break(b) class::function; break(b) class::function(type, type) 都是在函数入口进行断点
info b 可以查看当前所有标记了的断点
delete bnumber 可以删除指定的断点,其中bnumber是断点号,delete则是删掉所有的断点
disable/enable bnumber 可以禁用/启用指定的断点
(3),gdb打印
p variable 打印当前的变量,区分不同的格式 p /x a 是按照十六进制的方式来输出a变量; p /d a 是按照十进制的方式来输出a变量
在打印数组时,可以设置打印数组的个数 set print elements 0 (不限制打印数量)
选择打印数组的范围 print *(arr + start_index)@num 是打印数组arr从第start index起的num个数组元素的内容
x address 打印地址内容,x/nfu address,其中n是输出单元个数,f输出格式(如x是16进制,类似print格式),u是表明一个单元的长度(如b是一个byte,h是两个byte,w是四个byte,g是八个byte)
举个例子的是 x /16xb arr 的方式是在arr地址开始以16进制打印16个字节
(4),gdb调试命令
backtrace(bt) 显示当前执行的堆栈信息, bt full 加个full则显示所有参数信息
step(s) 调入下一步的单步调试命令,有函数会进入函数调用
next(n) 单步跟踪,有函数则不会进入函数调用
frame(f) n 是切换当前的栈帧,n是对应的bt里面的栈帧的序号
info(i) frame 打印当前的栈帧信息
info(i) locals 打印当前栈帧的局部变量
info registers 打印寄存器信息(除了浮点数寄存器) info all-registers 打印所有寄存器信息
info threads 打印当前正在运行的线程信息
watch expression ,可以是整型变量,也可以是指针变量,
info watch 则可以查看所有的观察点
list 则可以展示源代码,disassemble func 查看函数执行的汇编码
3,gdb调试coredump步骤
(1),如果程序coredump没有产生coredump文件,需要设置系统设置的core dump文件大小,命令:ulimit -c number
(2),对生成的coredump文件,用gdb进去,命令: gdb coredump exefile.out
(3),查看当前的栈信息,info locals 可以打印所有的局部变量的信息
可以发现一个AClass类的局部变量, 怀疑是内存写坏了的问题,打印该类的指针: p AClassPoint 输出该类的地址为 0xff1234
然后 x /16xg 0xff1234 可以看看该类的内存信息
因为 AClass 是一个虚类,发现打印的首地址是 0x0000b ,显然该地址不是一个正确的指向虚函数的虚表地址
那么,可以推断为该类的内存地址被写坏
(4),分析内存地址被写坏的可能性
典型的错误有 悬空指针裸写,数组越界写坏,被free后使用,等等情况