core dump记录
简介
core dump 是程序运行时在突然崩溃的那一刻的一个内存快照。操作系统在程序发生异常而异常在进程内部又没有被捕获的情况下,会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在一个 core 文件里。这个 core 文件是二进制文件,可以使用 gdb、elfdump、objdump 或者 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文件的原因
首先考虑了系统限制问题,shell键入
ulimit -a
查看core文件有没有限制大小,如果大小为0,说明禁止了core文件的产生,可以通过ulimit -c unlimited
来解除限制其次考虑是不是程序实现和权限方面的问题:
- 程序设置了用户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