一、错误代号
一般出现core会由以下几种类型的错误触发生成:
1. SIGSEGV 段错误(信号11),说白了就是访问了非法内存地址,无论是超出进程范围的(地址越界)还是系统不存在的内存访问(指针指向空)
2. SIGABRT 检测异常(信号6) 调用了abort()函数导致,最常见的是对释放的内存(free())再次进行释放,或者内存分配失败等原因的时候会触发
3. SIGBUS本意是指总线错误(信号7),一般出现在当你访问一段非法地址,并且这段地址物理上是不存在的。它类似于SIGSEGV,后者也是访问非法地址,但是这个地址是 虚拟地址空间的地址,SIGBUS正好相反,由于某些机器上,物理空间存在不连续的情况,访问到这些hole时,就会产生这个信号。硬件故障。
4. SIGILL 一般是硬件方面的问题,比如用%s格式直接输出string类型的(没有通过c_str()转换)一般会导致这个信号并退出进程(一般编译时就会提示cannot pass objects of non-POD type …call will abort at runtime)。
二、环境查看
查看堆栈信息:
1. backstrace, 简写bt :打印当前的函数调用栈的所有信息
2. frame[n], 简写f :切换到堆栈的第N层
3. up/down, 在堆栈中向上或者向下移动
4. info frame 打印更详细的当前栈层的信息,包括一些寄存器的信息
5. info args 打印出当前函数的参数名及值
6. info locals 打印出当前函数中所有局部变量及其值
查看变量:
命令:print [/fmt] [expr]
/fmt 是格式化的控制符,常用控制如下:
x 16进制 u 无符号
o 八进制 t 二进制
a 地址 c 字符常量
f 浮点数
expr 可以是当前程序运行中的const常量、变量、函数等内容,但是不能使用程序中所定义的宏。
表达式可以使用修饰符: var@n 表示将var看成长度是n的数组 注:这个我没看懂是什么意思
usage: p /x array
在GDB中可以随时查看以下三种变量:
1. 全局变量 2. 静态变量 3.局部变量
对于全局变量与局部变量名字产生冲突时,一般会打印局部变量的内容。为解决冲突,可以加入作用域修饰符:
scope::var 查看作用域内的var变量,scope可以是文件或函数
void Shop::Update()
{
static time_t tl = time(NULL);
}
可使用p 'Shop::Update'::t1进行查看
查看内存:
命令: x /nfu address 按照指定的格式查看内存数据
n 是一个正整数,表示显示的个数
f 表示显示的格式,参考之前的print的格式控制。
如果地址所指的是字符串,那么格式可以是s, 如果地址是指令地址,那么格式可以是i
u 表示从当前地址往后每个请求的字节数,如果不指定默认是4字节,b表示单字节,h表示双字节,w表示四字节,g表示八字节
例如命令:x /3xw 0xc8c9f90表示,从内存地址0xc8c9f90读取内容,以四字节为单位,连续读取三个单位,并且按16进制显示。