简介

core dump 是程序运行时在突然崩溃的那一刻的一个内存快照。操作系统在程序发生异常而异常在进程内部又没有被捕获的情况下,会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在一个 core 文件里。这个 core 文件是二进制文件,可以使用 gdbelfdumpobjdump 或者 Windows 下的 windebug 进行打开此文件,并分析里面的具体内容,找出 core dump 的具体原因,并解决问题。

在 Linux 系统下开发,时常会遇到程序突然崩溃了,且没有留下任何日志的情况,这时就可以查看 core 文件。从 core 文件中分析原因,通过 gdb 看出程序挂在哪里,分析前后的变量,找出问题的原因。

发生core dump的可能原因: + 空指针、非法指针 + 数组越界、内存踩踏 + 数据竞争 + 代码不规范、逻辑错误

启用core文件

默认情况下,程序运行崩溃导致 core dump,是不会生成 core 文件的,因为系统的 RLIMIT_CORE(核心文件大小)资源限制,默认情况下设置为 0。

使用 ulimit -c 命令可以查看 core 文件的大小,其中 -c 的含义是 core file size,单位是 blocks 也就是 KB 的意思。ulimit -c 命令后面可以写整数,表示生成写入值大小的 core 文件。如果使用 ulimit -c unlimited 设置无限大,则任意情况下都会产生 core 文件。

以下命令可在用户进程触发信号时启用 core dump 生成,并使用合理的名称将核心文件位置设置为 /tmp/。请注意,这些设置不会永久存储。

ulimit -c unlimited
echo 1 > /proc/sys/kernel/core_uses_pid
echo "/tmp/core-%e-%s-%u-%g-%p-%t" > /proc/sys/kernel/core_pattern

后面两条命令在运行时,即使是加了 sudo 执行,也可能会被提示权限不足。这可能是由于 shell 的重定向在命令前已经处理完成,因此重定向操作并没有被提升到超级用户权限,这就导致了 “Permission denied” 的错误。可以通过以下命令来解决这个问题:

echo 1 | sudo tee /proc/sys/kernel/core_uses_pid

echo "/tmp/core-%e-%s-%u-%g-%p-%t" | sudo tee /proc/sys/kernel/core_pattern

"/tmp/core-%e-%s-%u-%g-%p-%t" 的各个参数的含义: • %e:导致 core dump 的程序的可执行文件名。 • %s:导致 core dump 的信号编号。 • %u:导致 core dump 的程序的实际用户 ID。 • %g:导致 core dump 的程序的实际组 ID。 • %p:导致 core dump 的程序的进程 ID。 • %t:core dump 发生时的时间戳(自 epoch 时间以来的秒数)。

因此,/tmp/core-%e-%s-%u-%g-%p-%t 会生成包含如下信息的 core 文件:

/tmp/core-<executable>-<signal>-<uid>-<gid>-<pid>-<timestamp>

举个例子,如果一个进程名为 my_program,用户 ID 为 1000,组 ID 为 1000,进程 ID 为 12345,并且在 1617701234 时间点崩溃于信号 11,则生成的 core 文件名将是:

/tmp/core-my_program-11-1000-1000-12345-1617701234

使用gdb分析core文件

gdb <program_name> <core_dump_file>

gdb相关命令: + bt,打印堆栈 + list [func],查看函数代码 + print [var],打印变量的值 + info registers,查看寄存器状态,检查程序在崩溃时的上下文 + info signals,查看信号情况

通常情况下,分析 core dump 问题,除了 core 文件之外,还会结合程序的 log 信息和系统的 log 信息(包括 kernel log、systemd log 等)一起分析。
当然人为故意制造出来的 core dump(例如手动kill进程),有时候是分析不出来的。不是所有的 core dump 都可以分析出具体原因

作者:风吹过的月明
链接:https://zhuanlan.zhihu.com/p/707601911
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

不产生core文件的原因

  1. 首先考虑了系统限制问题,shell键入ulimit -a查看core文件有没有限制大小,如果大小为0,说明禁止了core文件的产生,可以通过 ulimit -c unlimited来解除限制

  2. 其次考虑是不是程序实现和权限方面的问题:

    • 程序设置了用户id(即调用setuid),但当前用户并非该程序文件的所有者
    • 程序设置了组id(即调用setgid),但当前用户并非该程序文件的组所有者
    • 用户没有当前目录或指定core文件产生目录的写权限
    • core文件太大,磁盘空间不足

产生core文件的缺省位置是程序所在目录,可以通过修改/proc/sys/kernel/core_pattern来指定core文件生成位置了名称。

通过查看core_pattern文件,发现其确实指定了一个路径,发现竟然是一个脚本程序,后来查看说明文件,才知道core_pattern中如果首先指定了一个 ‘|’ 管道符,则会将生成的core文件传递给后面所跟的脚本去处理。 至此,也就确定了问题的原因,| 管道符后面的脚本将我们的core文件给吞了,解决方法自然就是去掉这个脚本,换成自己指定的目录

core_pattern文件需要root权限写入(这里有两种方式): sudo bash -c "echo /tmp/core.txt > /proc/sys/kernel/core_pattern " echo "/tmp/core.txt" | sudo tee /proc/sys/kernel/core_pattern

To do

有一个工具叫 asan 建议看看它的文档 了解一下它能处理哪些错误引起的 crash