关于GDB的科普不是该短文的目标,本文旨在利用bt和f调试core文件。

概念解释

core dump: 当代码因为段错误(Segment Fault)退出时,操作系统会把当前内存中的信息持久化到磁盘中,生成一个名称为core的文件。利用该文件,我们可以分析出导致代码crash的事故现场。

core size:

利用下述命令可以查看系统设定的core文件大小,默认为0:

ulimit -a

要想使得可以生成core文件,修改core文件大小不为0即可(这里设定为大小无限制):

ulimit -c unlimited

事故制造

普通事故代码:

int main(){
    /* nullptr belongs to C++11 */
    char* p = nullptr;
    *p = '0';
    return 0;
}

复杂事故代码(main.cpp):

int main(){
    vector<int>a;
    vector<int>b;
    b.push_back(a[0]);
}

调试main.cpp的过程如下。

编译程序:

g++ -g main.cpp -o main

不出错。

执行程序:

./main

段错误,程序所在目录下生成core文件。

调试程序:

gdb main core

显示结果为库函数中的某行。想要定位到事故现场,查看调用栈。

bt

显示栈低内容,就是事故现场,假设栈低在第N层:

f N

直接抵达事故现场。

安利时间:必须推荐一个可视化GDB断点的操作(Ctrl+A+X)

调试技巧新增

1.带有命令行参数的调试

非调试状态下的运行:

./main.out input.txt  out.txt

调试状态:

gdb main

set args input.txt out.txt

2.查看类型信息

whatis var

这种场景下,仅仅输出类型的简单信息,例如int,vector等。如果需要了解变量的具体信息,使用如下:

ptype var

3.大型文件场景下断点

break 文件名:行数

4.条件断点

b 13 for i == 8

上述命令的含义是,如果i的值为8,就在第13行处设置断点。当i为8的时候,代码停在第13行。这个调试技巧在循环语句场景下使用。

参考:

1.文章一

一些不常见的调试命令,例如保存断点文件,条件断点