关键在于先启用生成再正确分析:需用ulimit -c unlimited临时或limits.conf永久开启core dump,配置core_pattern指定路径命名,编译时加-g保留调试符号,再用gdb ./prog core.xxx定位崩溃点。

Linux 中生成和分析 Core Dump 文件,关键在于两步:先让系统“愿意写”,再让工具“看得懂”。很多问题不是分析不了,而是根本没生成出来,或生成了但缺少调试信息。
让程序崩溃时生成 core 文件
默认几乎所有发行版都禁用 core dump,所以第一步永远是检查并开启:
- 运行 ulimit -c,如果输出是 0,说明被禁用
- 临时启用(当前终端及子进程有效):ulimit -c unlimited
- 永久生效:编辑 /etc/security/limits.conf,添加两行:
* soft core unlimited
* hard core unlimited
注意需确保 PAM 加载了 pam_limits.so(检查 /etc/pam.d/common-session) - systemd 服务要单独配置:在 .service 文件中加 LimitCORE=infinity
控制 core 文件存哪、叫什么名
默认 core 文件会出现在程序运行目录,名字是 core 或 core.
- 临时设置路径与命名:
echo "/var/crash/core.%e.%p.%t" | sudo tee /proc/sys/kernel/core_pattern
其中 %e 是程序名,%p 是 PID,%t 是时间戳(秒) - 永久设置:写入 /etc/sysctl.conf:
kernel.core_pattern = /var/crash/core.%e.%p.%t
然后执行 sudo sysctl -p - 路径必须存在且有写权限,所在分区不能满;若开头是 |(如 systemd-coredump),表示走管道处理,不落地为文件
用 gdb 正确加载和分析 core 文件
有 core 文件只是开始,真正定位问题靠的是符号信息和源码上下文:
- 编译时务必加 -g(例如:g++ -g -o myapp main.cpp),否则 gdb 只能看汇编
- 运行命令:gdb ./myapp core.myapp.12345(路径要对,二进制和 core 必须匹配同一版本)
- 进入 gdb 后常用命令:
bt —— 查看完整调用栈
bt full —— 显示各栈帧的局部变量值
info registers —— 检查寄存器(尤其 rip、rsp 是否异常)
list 或 frame 0 后 list —— 定位到源码行(依赖调试符号 + 源码路径未移动) - 如果提示 No symbol table is loaded,说明二进制被 strip 过,或编译没加 -g
常见卡点和快速排查方向
即使 ulimit 开了,仍没 core?优先看这几个硬性条件:
- 进程带 setuid/setgid(比如 root 启动的普通用户程序):内核默认禁止 dump,需设 echo 2 | sudo tee /proc/sys/fs/suid_dumpable
- 程序自己调用了 prctl(PR_SET_DUMPABLE, 0),主动放弃 dump 能力
- 磁盘配额(quota)超限、inode 耗尽、或 /var/crash 所在分区已满(查 dmesg | grep -i "core")
- 使用容器时,需在 docker run 中加 --ulimit core=-1,并挂载宿主机目录持久化 core











