前言

相信很多小伙伴在Linux环境下运行C++代码时都遇到过“段错误”,“核心转储”这种让人摸不着头脑的错误,但是又不知道如何定位到错误的位置。往往就放弃解决了,但是在实际工程中,出现这种错误是一定要解决的,不然项目拉跨了只能卷铺盖走人了。那么当项目工程量大的时候,我们来说说怎么快速定位到代码报错的位置。

Core dump的类型

1. 内存访问越界的问题(最典型的比如数组下标越界)
2. 堆栈溢出(使用了过大的局部变量,因为局部变量存储在栈中,容易导致溢出;函数递归的深度太大等等)
3. 非法指针(比如随意的强制转换指针的类型,或者使用了空指针)
4. 多线程同时读写某一个变量时,没有加线程锁。

假设有一段会core dump的程序:

//file:core_dump_test.cpp
#include<iostream>
using namespace std;
int vis[100];
int core_error(int list[])
{
    int a = list[6450];//访问越界 
    return a;
}
int main(){
    int tmp = core_error(vis);
    return 0;
}

使用gcc或者g++编译后,生成了可执行文件core_dump,运行可执行文件会报错如下:

深度学习段错误核心已转储_命令行


接下来我们就来说说如何定位错误。

第一步:生成core文件(Linux默认不生成,而我们要修改一下系统配置)

1.首先在命令行中输入

ulimit -a

会出现以下信息:

深度学习段错误核心已转储_命令行_02


core_file_size 为0,则说明当前系统限制了core文件的生成,我们需要在命令行输入

ulimit -c unlimited

这个操作只是暂时的,重启电脑后core_file_size就变回0了,避免程序不断coredump然后生成了一大堆的core文件。这里可能会出现这个错误(如果没有请跳过):

bash: ulimit: core file size: cannot modify limit: 不允许的操作

这是因为linux系统对普通用户有ulimit硬配置的限制。超出硬配置的上限就会不允许操作。但是问题不大,我们可以通过修改/proc/sys/fs下的文件来该硬配置,操作如下:

echo '1000000' > /proc/sys/fs/file-max
echo '1000000' > /proc/sys/fs/nr_open
file-max:系统内核最多可以打开的文件描述符数量
nr_open:某个进程可以打开的文件描述符数量

现在再次输入ulimit -c unlimited会出现:

深度学习段错误核心已转储_命令行_03


接下来再次运行可执行文件core_dump,将会生成core文件

深度学习段错误核心已转储_命令行_04

第二步:使用gdb来定位错误

执行命令

gdb  [可执行程序]  core文件
我这里是 gdb core_dump core

深度学习段错误核心已转储_命令行_05


上图告诉了我们出现错误的地方在 core_error函数里面。输入where可以显示出所有的堆栈信息。

gdb还有很多的功能,我自己也在学习过程中,希望分享出来和大家一起学习。创作不易,如果能帮助到你,是我的荣幸。