Linux Core Dump 完全指南:从原理到实战的崩溃调试手册。什么是core dump?程序报错core dumped怎么办?

跑得好好的程序突然崩溃,终端显示 Segmentation fault (core dumped),没有日志,没有报错堆栈,怎么排查?

目录


一、什么是 Core Dump?

字面含义

  • Core:早期计算机的内存叫"磁芯内存"(Magnetic Core Memory),这个称呼沿用至今,代指程序的内存状态。
  • Dumped:转储、倾倒。

Core Dump 就是当程序发生严重错误崩溃时,操作系统在进程退出前,将其当时的内存状态、寄存器值、函数调用栈、局部变量等所有运行信息,完整保存到一个文件(通常叫 core)中的过程。

核心价值

  1. 事后调试:无需复现崩溃场景,直接分析 core 文件就能找到崩溃点
  2. 保留现场:即使程序已经退出,也能查看崩溃瞬间的所有变量值、函数调用链
  3. 排查偶发 Bug:对于随机崩溃的问题,只要拿到 core 文件就能稳定分析,不用再"等它再崩一次"

二、什么时候会触发 Core Dump?

当程序收到以下未捕获的信号时,系统会自动触发 core dump:

信号 含义 常见触发场景
SIGSEGV 段错误 空指针解引用、数组越界、访问已释放内存
SIGABRT 主动中止 调用 abort()assert 断言失败
SIGBUS 总线错误 内存对齐错误、硬件故障
SIGFPE 算术异常 整数除以 0、浮点运算溢出
SIGILL 非法指令 执行了 CPU 不支持的指令、二进制文件损坏

三、从 0 到 1 开启 Core Dump

第一步:检查当前是否开启

bash 复制代码
ulimit -c
  • 输出 0:表示关闭,不会生成 core 文件
  • 输出 unlimited 或具体数字:表示已开启

第二步:临时开启(仅当前终端会话有效)

bash 复制代码
ulimit -c unlimited

第三步:永久开启(所有用户生效)

编辑 /etc/security/limits.conf,添加以下两行:

复制代码
* soft core unlimited
* hard core unlimited

如果崩溃的程序是 systemd 管理的服务,需要在对应的 service 文件中添加:

复制代码
[Service]
LimitCORE=infinity

第四步:配置 core 文件的存储路径和命名规则

默认的 core 文件可能在当前目录生成,也可能被 systemd 接管。如果想自定义存储位置和文件名,修改内核参数 core_pattern

临时生效

bash 复制代码
sudo sysctl -w kernel.core_pattern=/var/crash/core-%e-%p-%t

永久生效

/etc/sysctl.conf 中添加:

复制代码
kernel.core_pattern=/var/crash/core-%e-%p-%t

常用占位符说明

占位符 含义
%e 可执行文件名
%p 进程 PID
%t 崩溃时的时间戳(秒)
%u 进程用户 ID
%s 触发崩溃的信号编号
%h 主机名

注意:提前创建存储目录并设置写权限,否则 core 文件无法生成:

bash 复制代码
sudo mkdir -p /var/crash
sudo chmod 777 /var/crash

四、调试前的必备准备:编译时加调试符号

这一步非常重要! 如果编译时没有添加调试信息,gdb 只能看到内存地址,无法显示对应的源码行号和变量名,core 文件基本等于废了。

编译时必须添加 -g 参数,建议同时用 -O0 关闭优化,避免优化后代码行号和实际执行位置对不上:

bash 复制代码
gcc -g -O0 -o my_app my_app.c

如果是 CMake 项目,设置构建类型为 Debug 即可:

cmake 复制代码
set(CMAKE_BUILD_TYPE Debug)

五、实战:用 GDB 分析 Core Dump

1. 准备示例代码

我们写一个会触发段错误的程序:

c 复制代码
// crash_demo.c
#include <stdio.h>

int main() {
    int *ptr = NULL;
    printf("即将访问空指针...\n");
    *ptr = 42;  // 空指针解引用,触发 SIGSEGV
    return 0;
}

2. 编译并运行

bash 复制代码
gcc -g -O0 -o crash_demo crash_demo.c
./crash_demo

输出:

复制代码
即将访问空指针...
段错误 (核心已转储)

3. 找到 core 文件

根据刚才配置的 core_pattern,core 文件应该在 /var/crash/ 目录下,文件名类似 core-crash_demo-12345-1629876543

4. 用 GDB 加载分析

bash 复制代码
gdb ./crash_demo /var/crash/core-crash_demo-12345-1629876543

进入 gdb 交互界面后,常用命令如下:

查看崩溃调用栈

gdb 复制代码
(gdb) bt
#0  0x0000555555555149 in main () at crash_demo.c:6
6           *ptr = 42;  // 空指针解引用,触发 SIGSEGV

栈顶的 #0 就是崩溃发生的具体位置,直接定位到第 6 行代码。

查看变量值

gdb 复制代码
(gdb) print ptr
$1 = (int *) 0x0

可以看到 ptr 的值是 0x0,确认是空指针解引用导致的问题。

其他常用命令

gdb 复制代码
frame 0             # 切换到第 0 层栈帧(崩溃点)
info locals         # 查看当前函数所有局部变量
list                # 查看崩溃点附近的源码
info registers      # 查看 CPU 寄存器状态

如果是多线程程序,还可以用:

gdb 复制代码
info threads        # 查看所有线程状态
thread 2            # 切换到第 2 个线程
thread apply all bt # 打印所有线程的调用栈

六、现代 Linux 的 Core Dump 管理:systemd-coredump

现在很多主流发行版(Ubuntu 20.04+、CentOS 8+、Debian 11+)默认使用 systemd-coredump 接管 core 文件,不会在当前目录生成 core 文件,而是统一存储到 /var/lib/systemd/coredump/ 下,用 coredumpctl 工具管理:

bash 复制代码
coredumpctl list           # 查看所有 core dump 记录
coredumpctl info           # 查看最近一次崩溃的详情
coredumpctl debug          # 直接用 gdb 调试最近的崩溃
coredumpctl debug <PID>    # 调试指定 PID 的 core 文件

七、生产环境避坑指南

1. 安全问题

core 文件里可能包含密码、API 密钥、用户数据等敏感信息,绝对不能传到公开的地方,分析完成后及时删除,建议设置文件权限为 600

bash 复制代码
chmod 600 /var/crash/core-*

2. 磁盘空间

core 文件的大小和程序占用的内存差不多,可能达到几 GB 甚至几十 GB,容易把磁盘撑爆。可以设置大小限制:

bash 复制代码
ulimit -c 102400  # 限制 core 文件最大为 100MB

或者定期清理旧的 core 文件:

bash 复制代码
find /var/crash -name "core.*" -mtime +7 -delete

3. 找不到 core 文件?排查步骤

  • 检查 ulimit -c 是否开启
  • 检查 core_pattern 配置的路径是否有写权限
  • 检查磁盘空间是否满了
  • 如果是 setuid 程序,需要设置 fs.suid_dumpable=2

4. GDB 加载 core 文件显示 ?? 没有行号?

  • 检查编译时是否加了 -g 参数
  • 检查加载的可执行文件和崩溃时的是不是同一个版本,不能重新编译后再分析旧的 core 文件,否则符号表对不上
相关推荐
Lifangyun_WD15 分钟前
第一次租 GPU 服务器怎么开始?镜像、SSH、数据存储和停机前要做什么
服务器·云计算·gpu算力·gpu算力租赁
DevLoom_1 小时前
SD卡插电脑提示:驱动器中的磁盘未被格式化?恢复数据正确处理步骤
运维·服务器·电脑
MayZork3 小时前
Windows 与 Linux 下 vcpkg 的安装部署指南
linux·运维·windows
yyuuuzz3 小时前
记一次 VPS 性能排查:共享 CPU 突发额度导致的限流
运维·服务器·人工智能
冰雪青松3 小时前
Ubuntu 运维命令大全:从入门到精通的实战参考手册
运维·服务器·ubuntu
前端 贾公子3 小时前
第09章:上下文与记忆 (2)
java·服务器·前端
zbyyd3 小时前
Linux 进程间通信学习笔记
linux·笔记·学习
CDN3604 小时前
节点智能调度实操:解决出海区域访问快慢不均、节点拥堵、跨洋延迟高,CDN 全网择优落地方案
运维·服务器·网络
roman_日积跬步-终至千里4 小时前
【数据治理(6)】DataOps 不是调度工具,而是让数据产品长期可信的运行机制
java·服务器·网络