核心转储

在 Linux 系统中,常将“主内存”称为核心(core),而核心映像(core image) 就是 “进程”(process)执行当时的内存内容。当进程发生错误或收到“信号”(signal) 而终止执行时,系统会将核心映像写入一个文件,以作为调试之用,这就是所谓的核心转储(core dump)。

通常在系统收到特定的信号时由操作系统生成。信号可以由程序执行过程中的异常触发,也可以由外部程序发送。动作的结果一般是生成一个某个进程的内存转储的文件,文件包含了此进程当前的运行堆栈信息。有时程序并未经过彻底测试,这使得它在执行的时候一不小心就会找到破坏。这可能会导致核心转储(core dump)。

当在一个程序崩溃时,系统会在指定目录下生成一个core文件,我们就可以通过 core文件来对造成程序崩贵的原因进行调试定位。

开启核心转储

默认情况下,Linux 没有打开core文件生成功能,通过以下命令打开core文件的生成:

# 不限制产生 core 的大小
ulimit -c unlimited

unlimited 意思是系统不限制core文件的大小,只要有足够的磁盘空间,会转存程序所占用的全部内存,如果需要限制系统产生 core 的大小,可以使用以下命令:

# core 最大限制大小为 409600 字节
ulimit -c 409600

如果需要关装核心转储功能,只需要将限制大小设为0 即可:

ulimit -c 0

上述操作在一个终端中有效,退出或者新打开终端时无效,可以在将上述配置加入到 /etc/profile 中:

# 编辑 profile 文件
vi /etc/profile

# 将下行加到入profile 文件中
ulimit -c unlimited

使用GDB调试 core 文件

首先我们来编写一个产生错误的程序,vi test.c

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
  int *p = NULL;

  // 给一个NULL指令赋值,会产生 Segmentation fault 错误
  *p = 100;

  return 0;
}

以上程序给一个空指令赋值,这是C语言编程中遇到的段错误,程序运行后,如果开启了核心转储后,就会产生一个 core 文件。

# 编译 test.c 生成 test 程序
gcc test.c -o test -g -MD

# 运行该程序
./test

运行后,我们可以看到 Segmentation fault (core dumped) 提示信息,表示已经在当前目录下产生了一 core 文件,通过 ls -l core 命令可以查看:

root@thead-910:~# ls -l core
-rw------- 1 root root 225280 Jan  6 10:51 core

下面我样就可以通过 core 来进行调试:

root@thead-910:~# gdb test core
GNU gdb (Debian 10.1-1.7) 10.1.90.20210103-git
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "riscv64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
[New LWP 1134]
Core was generated by `./test'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000002ae6775600 in main (argc=1, argv=0x3fffb22d18) at test.c:9
9        *p = 100;

通过 GDB 可以看到程序的第9行出错。

如果我们想一步步调试,那么可以在gdb中打断点(b),然后运行(r),或者一步步(s)调试,

(gdb) b test.c:9
Breakpoint 1 at 0x2ae67755f8: file test.c, line 9.
(gdb) r
Starting program: /root/test

Breakpoint 1, main (argc=1, argv=0x3ffffffce8) at test.c:9
9        *p = 100;
(gdb) p p
$1 = (int *) 0x0
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x0000002aaaaaa600 in main (argc=1, argv=0x3ffffffce8) at test.c:9
9        *p = 100;
(gdb) quit
A debugging session is active.

        Inferior 1 [process 1198] will be killed.

Quit anyway? (y or n) y

使用 GDB 调式 core 的命令格式如下:

gdb <程序> <core文件>

results matching ""

    No results matching ""