Linux应用开发之coredump

前言

    程序崩溃往往是最不好调试的,如果是很容易复现的现象,可能我们还可以比较容易分析出问题所在。但是对于那种需要几天,或者在某种特殊条件下才能触发的现象。我们总不能一直守着,所以这个时候就需要系统帮我们把崩溃的一些信息记录下来,也就是接下来要提到的coredump

什么是coredump

    当程序运行的过程中异常终止或崩溃,操作系统会将程序当时的内存状态, 寄存器信息 , 系统状态等记录下来,保存在一个文件中,这种行为就叫做core dump。

core文件生成

    默认情况下,core文件是不会生成的,也就是程序崩溃了,你是找不到core文件的。我们可以通过下面的命令来查看core dump是否开启。


1
ulimit -c  # 如果为 0 表示coredump开关处于关闭状态

假如没有开启,那要怎么开启呢?只要设置一下core文件大小:


1
2
ulimit -c 1024         # 1024个blocks,一般1block=512bytes
ulimit -c unlimited    # 取消大小限制

只要设置core文件大小后,就开启了,大小就根据自己的需要来确定了。对于长时间之后才崩溃的,肯定要设置大一点。

* ulimit命令的用法可以自己去查

core文件存放位置

    core文件默认的存放位置与对应的可执行程序在同一目录下,文件名为core。可以通过下面的命令查看:


1
cat  /proc/sys/kernel/core_pattern

返回值是不是很奇怪,但是它对应的就是程序所在目录。想深究,自己动手!^_^

如果不想存放在默认位置,可以修改上面文件的值:


1
echo "/tmp/core"> /proc/sys/kernel/core_pattern

gdb调试coredump

    有了core文件之后,还得考虑怎么使用该文件,这时候gdb又要上场了。我们先举个例子: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
 
 
 
 
#define CORE_SIZE (500 * 1024 * 1024)
 
 
int enableCoreDump(int iFlag)
{
    struct rlimit stRlim;
 
 
    /* core */
    stRlim.rlim_cur = stRlim.rlim_max = iFlag ? CORE_SIZE : 0;
    if (0 != setrlimit(RLIMIT_CORE, &stRlim))   //设置core文件大小
    {
        printf("Error: setrlimit failed\n");
        return -1;
    }
    else
    {
        printf("Set coredump file size to %lu\n", stRlim.rlim_cur);
        return 0;
    }
}
 
 
 
 
int main()
{
  int* p = NULL;
  enableCoreDump(1);
 
  *p = 12;
 
  printf("finish\n");
}

Linux提供了API来设置core文件的大小,所以上面我们使用setrlimit来设置core文件的大小。

上面就是一个简单的空指针引起的崩溃。

(1)编译:


1
gcc -g coredunp.c -o  coredunp

要加上-g才能使用gdb调试。

(2)运行:

崩溃后产生core文件。

(3)使用gdb调试core文件


1
gdb coredump core

可以从上面看出程序崩溃的位置,coredump.c的第33行。可以通过bt看一下堆栈:

这样基本就可以定位到是在哪里调用导致程序崩溃了。

总结

    做应用开发,一般情况下会开启coredump,这样对于定位bug有很大的帮助。对于嵌入式开发,很多时候出现bug是在一些特殊的情况下,所以一般是建议开启coredump,除非有很高的性能要求。