1. coredump是什么

Coredump叫做 核心转储 ,它是进程运行时在突然崩溃的那一刻的 一个内存快照 。操作系统在程序发生异常而异常在进程内部又没有被捕获的情况下,会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在一个 core文件里
core文件是 二进制文件 ,可以使用 gdb elfdump objdump 或者windows下的 windebug 、solaris下的 mdb 进行打开分析里面的具体内容。

注:core是在半导体作为内存材料前的线圈,当时用线圈当做内存材料,线圈叫做core。用线圈做的内存叫做core memory。故coredump也可称为core memory dump,真是个充满历史味道的词儿。

2. 用在什么地方

在linux下开发时,如果程序突然崩溃了,也没有任何日志。这时可以查看core文件。从core文件中分析原因,通过gdb看出程序挂在哪里,分析前后的变量,找出问题的原因。

core dump 对于编程人员诊断和调试程序是非常有帮助的,因为对于有些程序错误是很难重现的,例如指针异常,而 core dump 文件可以再现程序出错时的情景。

3.怎么生成core文件

虽然我们知道进程在crash的时候会产生core文件,但是有时候却发现进程虽然coredump了,但是我们却找不到core文件。

原因是,在Linux下是需要进行设置的。

1. 设置文件大小

使用 ulimit -c value 可以设置 core文件 的大小。 -c 的含义是 core file size ,单位是 blocks

  • value=0 ,则不会产生core文件;
  • value值太小 ,则core文件也不会产生,因为core文件一般都比较大。
  • ulimit -c unlimited 设置无限大,则任意情况下都会产生core文件。
  • 这种修改为临时限制,只存活于当前SHELL会话,仅影响当前SHELL。

    2. 获取当前core file名称格式与保存位置

    方法1: cat /proc/sys/kernel/core_pattern

    root@OpenWrt:~# cat /proc/sys/kernel/core_pattern
    /tmp/%e.%p.%s.%t.core
    

    方法2: /sbin/sysctl kernel.core_pattern

    root@OpenWrt:~# /sbin/sysctl kernel.core_pattern
    kernel.core_pattern = /tmp/%e.%p.%s.%t.core
    

    3. 修改core file名称格式与保存位置

    echo /mnt/sd/%e.%p.core > /proc/sys/kernel/core_pattern
    

    修改/proc/sys/kernel/core_pattern文件,由于/proc目录本身是动态加载的,每次系统重启都会重新加载,因此这种方法只能作为临时修改

    4. 保存修改并全局生效

  • 修改/etc/profile文件,在文件末尾添加:
  • ulimit -c unlimited		#设置文件大小
    echo /tmp/%e.%p.%s.%t.core > /proc/sys/kernel/core_pattern	#设置文件文件名格式和文件存储位置
    

    为了更详尽的记录core dump当时的系统状态,可通过以下参数来丰富core文件的命名:

  • %%------单个%字符
  • %p------所dump进程的进程ID,pid
  • %u------所dump进程的实际用户ID, uid
  • %g------所dump进程的实际组ID, group
  • %s------导致本次core dump的信号, signal
  • %t------core dump的时间 (由1970年1月1日计起的秒数)
  • %h------主机名, hostname
  • %e------程序文件名, executing program name
  • 重启系统.
  • 运行程序。
    当程序coredump时,生成的core文件命名按照上面定义的规则加上了程序名称、coredump时间,进程ID等信息,并放到了指定目录/tmp/下。
  • 3. 使用gdb调试core file简单示例

    写空指针错误

    #include <stdio.h>
    void coredump(void)
    	int *null_ptr = NULL;
    	*null_ptr = 10;
    int main(){
    	// 对空指针指向的内存区域写,会发生段错误 -->产生core文件
        printf("hello coredump\n");
        coredump();
        printf("will be never reached\n");
    	return 0;
    

    编译,运行,生成corefile

    使用gdb调试core file

    gdb 可执行程序(包括路径) 对应的corefile
    

    可以直接看到发生错误的地点。

    调试无调试信息的程序

    此时可以看到gdb提示无调试信息,不能像加了-g选项一样,可以直接看到发生段错误的地点。
    这个时候需要查看函数的call stackbt or where,看一下是在哪个地方发生的错误 f 0,并进入这个函数,查看其反汇编disassemble代码来定位问题的原因。
    要想使用反汇编代码定位问题,就需要明确汇编代码与所写代码的对应关系。这个需要积累才能加快调试速度。

    4. FAQ

    Q: 程序core dump了,但是没有生成core。

    A: 打开ulimited -c unlimited 开关。

    Q: 程序core dump了,也产生了core文件, 但core大小为了0。 gdb分析的时候, 会出现is not a core dump: File format not recognized.
    A: 打开ulimited -c unlimited 开关。

    Q: 程序core dump了, 也产生了core文件, core大小也不为0, 也设置了ulimited -c unlimited, 但是, gdb分析的时候, 依然出现is not a core dump: File format not recognized
    A: 执行 cat /proc/pid_num/limits查看了一下这个进程的Max core file size值是不是unlimited。 若不是,找到设置文件, 并修改之, 重启服务进程, 然后看看进程的Max core file size值,确认是unlimited即可。

    Q:上面的设置都没问题,但是还是会提示is not a core dump: File format not recognized

    A:请确保GDB加载时的格式是正确的。

    Q:在/proc/sys/kernel/目录下没有core_pattern文件
    A:这是由于内核编译时,没有使能core dump功能所致。重新配置内核
    编译,烧写即可。

    出现is not a core dump: File format not recognized, 很有可能是core文件不完整导致的,最开始的时候, 大致看看core文件的大小就能大概判断了。 那就真正打开core文件的大小限制吧。