Linux 下段错误生成 core 文件的相关配置

core dump 介绍

在 Linux 环境下调试 C/C++ 程序时,经常会因为内存访问错误产生段错误(核心已转储),而在当前目录却找不到转储的 core 文件,此时需要检查系统 core dump 配置是否打开。

如果打开系统 core dump 功能,那么在程序运行报段错误后,系统就会将程序的内存映像转储到硬盘,随后可以用 gdb 对生成的 core 文件进行分析,还原程序发生段错误时刻的堆栈调用信息。

查看系统 core dump 配置

通过 ulimit -a 命令查看系统 core 文件的大小限制,可以看到第一行 core file size 设置为 0,即没有打开 core dump 开关。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lhx@ubuntu:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 31400
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 31400
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

设置系统生成的 core 文件大小

使用 ulimit -c [kbytes] 命令设置系统允许生成的 core 文件大小。

  • ulimit -c 0 :不产生 core 文件
  • ulimit -c 100 :设置 core 文件最大为 100kb
  • ulimit -c unlimited :不限制 core 文件大小

通常会设置为 unlimited,即不限制文件大小。

1
lhx@ubuntu:~$ ulimit -c unlimited 

然后,再查看下系统 core dump 配置,可以看到第一行 core file size 变为了 unlimited。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lhx@ubuntu:~$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 31400
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 31400
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

配置 core 文件保存路径

core 文件具体存放在哪个目录取决于系统参数 kernel.core_pattern:

1
2
root@ubuntu:# cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E

修改 /proc/sys/kernel/core_pattern 设置格式化的 core 文件保存位置或文件名:

1
2
3
4
5
6
7
root@ubuntu:# cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E

root@ubuntu:# echo "/home/lhx/test/coredump/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

root@ubuntu:/home/lhx/test/coredump# cat /proc/sys/kernel/core_pattern
/home/lhx/test/coredump/core-%e-%p-%t

% E:添加可执行程序的完整路径
% e:添加可执行程序名
% p:添加 pid
% t:进程奔溃的时间戳
% s:添加导致产生 core 的信号
% u - 添加当前 uid
% g - 添加当前 gid

然后重新设置 ulimit,再测试一下,发现生成了对应的 core 文件:

1
2
3
4
5
root@ubuntu:/home/lhx/test/coredump# ulimit -c unlimited
root@ubuntu:/home/lhx/test/coredump# ./a.out
段错误 (核心已转储)
root@ubuntu:/home/lhx/test/coredump# ls
a.out core-a.out-9209-1653703102 coredump.c

复杂情况处理

  1. 一般情况下,使用 ulimit -c unlimited 命令后,会默认在当前目录生成对应 core 文件。

  2. 如果当前目录没有找到 core 文件,使用命令 cat /proc/sys/kernel/core_pattern 却看到 /usr/share/apport/apport 类似的路径,注意这个并不是系统保存的路径!Ubuntu 下 coredump 会被 Apport 来处理。

  3. 此时建议进行格式化设置 core 文件路径和名称,然后,基本就能正常显示 core 文件。

  4. 如果还是找不到 core 文件,则使用下面的终极方法:

使用 cat /var/log/apport.log 查看日志:

1
2
3
4
5
6
root@ubuntu:/usr/share/apport# cat /var/log/apport.log 
ERROR: apport (pid 3164) Fri May 27 22:29:20 2022: called for pid 3163, signal 11, core limit 18446744073709551615, dump mode 1
ERROR: apport (pid 3164) Fri May 27 22:29:20 2022: ignoring implausibly big core limit, treating as unlimited
ERROR: apport (pid 3164) Fri May 27 22:29:20 2022: executable: /home/lhx/test/coredump/a.out (command line "./a.out")
ERROR: apport (pid 3164) Fri May 27 22:29:20 2022: executable does not belong to a package, ignoring
ERROR: apport (pid 3164) Fri May 27 22:29:20 2022: writing core dump to core._home_lhx_test_coredump_a_out.0.b0a0dac1-9489-4362-b93e-5b795f497130.3163.16880 (limit: -1)

会看到一行关键信息,包含可执行程序名称、路径和时间戳,这就是 core 文件:

1
ERROR: apport (pid 3164) Fri May 27 22:29:20 2022: writing core dump to core._home_lhx_test_coredump_a_out.0.b0a0dac1-9489-4362-b93e-5b795f497130.3163.16880 (limit: -1)

然后全局范围内搜索文件名,会发现 core 文件位于 /var/lib/apport/coredump/ 目录:

1
2
lhx@ubuntu:/$ sudo find . -name "core._home_lhx_test_coredump_a_out.0.b0a0dac1*"
/var/lib/apport/coredump/core._home_lhx_test_coredump_a_out.0.b0a0dac1-9489-4362-b93e-5b795f497130.3163.16880

其他注意事项

  1. 注意 ulimit -c unlimited 命令只针对当前 shell 窗口有效。
  2. 格式化设置 core 文件路径和名称时,注意要用 root 或 sudo 权限。
  3. 如果上述方法还是不行,建议全局使用 root 账户。