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

📅 2026/8/26 16:48:08
Linux Core Dump 完全指南:从原理到实战的崩溃调试手册。什么是core dump?程序报错core dumped怎么办?
跑得好好的程序突然崩溃终端显示Segmentation fault (core dumped)没有日志没有报错堆栈怎么排查目录一、什么是 Core Dump字面含义核心价值二、什么时候会触发 Core Dump三、从 0 到 1 开启 Core Dump第一步检查当前是否开启第二步临时开启仅当前终端会话有效第三步永久开启所有用户生效第四步配置 core 文件的存储路径和命名规则四、调试前的必备准备编译时加调试符号五、实战用 GDB 分析 Core Dump1. 准备示例代码2. 编译并运行3. 找到 core 文件4. 用 GDB 加载分析查看崩溃调用栈查看变量值其他常用命令六、现代 Linux 的 Core Dump 管理systemd-coredump七、生产环境避坑指南1. 安全问题2. 磁盘空间3. 找不到 core 文件排查步骤4. GDB 加载 core 文件显示 ?? 没有行号一、什么是 Core Dump字面含义Core早期计算机的内存叫“磁芯内存”Magnetic Core Memory这个称呼沿用至今代指程序的内存状态。Dumped转储、倾倒。Core Dump就是当程序发生严重错误崩溃时操作系统在进程退出前将其当时的内存状态、寄存器值、函数调用栈、局部变量等所有运行信息完整保存到一个文件通常叫core中的过程。核心价值事后调试无需复现崩溃场景直接分析 core 文件就能找到崩溃点保留现场即使程序已经退出也能查看崩溃瞬间的所有变量值、函数调用链排查偶发 Bug对于随机崩溃的问题只要拿到 core 文件就能稳定分析不用再“等它再崩一次”二、什么时候会触发 Core Dump当程序收到以下未捕获的信号时系统会自动触发 core dump信号含义常见触发场景SIGSEGV段错误空指针解引用、数组越界、访问已释放内存SIGABRT主动中止调用abort()、assert断言失败SIGBUS总线错误内存对齐错误、硬件故障SIGFPE算术异常整数除以 0、浮点运算溢出SIGILL非法指令执行了 CPU 不支持的指令、二进制文件损坏三、从 0 到 1 开启 Core Dump第一步检查当前是否开启ulimit-c输出0表示关闭不会生成 core 文件输出unlimited或具体数字表示已开启第二步临时开启仅当前终端会话有效ulimit-cunlimited第三步永久开启所有用户生效编辑/etc/security/limits.conf添加以下两行* soft core unlimited * hard core unlimited如果崩溃的程序是 systemd 管理的服务需要在对应的 service 文件中添加[Service] LimitCOREinfinity第四步配置 core 文件的存储路径和命名规则默认的 core 文件可能在当前目录生成也可能被 systemd 接管。如果想自定义存储位置和文件名修改内核参数core_pattern临时生效sudosysctl-wkernel.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 文件无法生成sudomkdir-p/var/crashsudochmod777/var/crash四、调试前的必备准备编译时加调试符号这一步非常重要如果编译时没有添加调试信息gdb 只能看到内存地址无法显示对应的源码行号和变量名core 文件基本等于废了。编译时必须添加-g参数建议同时用-O0关闭优化避免优化后代码行号和实际执行位置对不上gcc-g-O0-omy_app my_app.c如果是 CMake 项目设置构建类型为 Debug 即可set(CMAKE_BUILD_TYPE Debug)五、实战用 GDB 分析 Core Dump1. 准备示例代码我们写一个会触发段错误的程序// crash_demo.c#includestdio.hintmain(){int*ptrNULL;printf(即将访问空指针...\n);*ptr42;// 空指针解引用触发 SIGSEGVreturn0;}2. 编译并运行gcc-g-O0-ocrash_demo crash_demo.c ./crash_demo输出即将访问空指针... 段错误 (核心已转储)3. 找到 core 文件根据刚才配置的core_patterncore 文件应该在/var/crash/目录下文件名类似core-crash_demo-12345-1629876543。4. 用 GDB 加载分析gdb ./crash_demo /var/crash/core-crash_demo-12345-1629876543进入 gdb 交互界面后常用命令如下查看崩溃调用栈(gdb) bt #0 0x0000555555555149 in main () at crash_demo.c:6 6 *ptr 42; // 空指针解引用触发 SIGSEGV栈顶的#0就是崩溃发生的具体位置直接定位到第 6 行代码。查看变量值(gdb) print ptr $1 (int *) 0x0可以看到ptr的值是0x0确认是空指针解引用导致的问题。其他常用命令frame 0 # 切换到第 0 层栈帧崩溃点 info locals # 查看当前函数所有局部变量 list # 查看崩溃点附近的源码 info registers # 查看 CPU 寄存器状态如果是多线程程序还可以用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工具管理coredumpctl list# 查看所有 core dump 记录coredumpctl info# 查看最近一次崩溃的详情coredumpctl debug# 直接用 gdb 调试最近的崩溃coredumpctl debugPID# 调试指定 PID 的 core 文件七、生产环境避坑指南1. 安全问题core 文件里可能包含密码、API 密钥、用户数据等敏感信息绝对不能传到公开的地方分析完成后及时删除建议设置文件权限为600chmod600/var/crash/core-*2. 磁盘空间core 文件的大小和程序占用的内存差不多可能达到几 GB 甚至几十 GB容易把磁盘撑爆。可以设置大小限制ulimit-c102400# 限制 core 文件最大为 100MB或者定期清理旧的 core 文件find/var/crash-namecore.*-mtime7-delete3. 找不到 core 文件排查步骤检查ulimit -c是否开启检查core_pattern配置的路径是否有写权限检查磁盘空间是否满了如果是 setuid 程序需要设置fs.suid_dumpable24. GDB 加载 core 文件显示??没有行号检查编译时是否加了-g参数检查加载的可执行文件和崩溃时的是不是同一个版本不能重新编译后再分析旧的 core 文件否则符号表对不上