马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
程序崩了但什么线索都没留下,是最难受的排查场景。Linux 的 core dump 就是干这个的:进程异常终止的瞬间,把内存映像.dump 到磁盘。这篇讲清它是什么、怎么开、文件长什么样、以及怎么用 GDB 定位到具体哪一行。
一、core dump 是什么
core dump(核心转储)指程序异常终止时,操作系统把该程序的内存映像保存到磁盘的机制。它记录了崩溃瞬间的内存状态,是定位程序错误最重要的手段之一。
常见触发原因:
- 段错误 Segmentation fault:访问无效内存地址,比如未分配或已释放的内存;
- 空指针引用 Null pointer dereference:拿 null 指针去读数据;
- 内存访问越界 Out of bounds:数组、结构体访问超出边界;
- 使用已释放内存 Use after free:释放后还读写;
- 栈溢出 Stack overflow:递归太深或栈上分配过多;
- 除以零 Division by zero;
- 无效指令 Invalid instruction:执行了不存在的机器指令;
- 硬件故障或内核崩溃:内存损坏等环境异常。
二、怎么让 core 文件生成出来
不是默认就 dump 的,要 ulimit -c 放开。先查当前限制:
ulimit -c
输出含义:
- 数字(KB):当前用户允许生成的 core 文件大小上限;
- unlimited:不限大小;
- 0:不允许生成 core 文件(默认值,所以你通常看不到 core)。
放开:
ulimit -c unlimited
但 ulimit 只对当前 shell 会话有效,想永久生效得写进 /etc/security/limits.conf 或 systemd 的 LimitCORE。
三、core 文件放哪、叫什么
默认在当前工作目录下,文件名一般是 core 或 core.PID(PID 是崩溃进程的 ID)。
想改路径和命名格式,改 /proc/sys/kernel/core_pattern:
echo "core-%e-%p-%t" | sudo tee /proc/sys/kernel/core_pattern
另外 ulimit -c 控制 core 文件最大大小,两个一起决定能不能 dump 出来。
四、怎么分析
用 GDB(GNU Debugger) 加载 core 文件和对应的可执行文件:
gdb ./demo core
进去之后看堆栈跟踪、变量值,崩溃位置和原因基本就浮出来了。注意:可执行文件必须是带调试符号的那一份(-g 编译),发布版 strip 过的定位会很吃力。
五、Demo:从崩溃到定位
一个空指针写操作导致段错误的最小示例:
#include <stdio.h>
void cause_crash() {
char *ptr = NULL;
*ptr = 'A'; // 空指针写操作,段错误
}
int main() {
cause_crash();
return 0;
}
编译运行:
gcc -g -o demo demo.c
./demo # 触发 coredump
用 GDB 分析:
gdb ./demo core
在 GDB 里打 bt 看堆栈:
(gdb) bt
#0 0x00005555555546e8 in cause_crash () at demo.c:6
#1 0x0000555555554701 in main () at demo.c:11
堆栈直接告诉你:问题出在 cause_crash 函数的第 6 行(空指针引用导致段错误)。这种简单场景下,修复就是在写操作前加个空指针检查。
六、正常排查流程
- 拿到 core 文件:确认它生成在哪(没生成就先看 ulimit 和 core_pattern);
- 分析 core:GDB 加载 +
bt 看堆栈、p 看变量;
- 定位原因:判断是内存访问错误、空指针、还是数据破坏;
- 改代码:修内存管理、补错误检查和异常处理;
- 回归验证:单测、集成测试确保不再崩。
七、为什么有时候 core 文件生不出来
几种常见原因:
- core 大小为 0:ulimit 限制,改成 unlimited 试试;
- 挂载点满了(比如
/dev/loop 相关挂载空间不足),写不进去——这时候日志 里会一直刷写失败,不是权限问题;
- core_pattern 指向了不存在的目录或没有写权限;
- 进程被 SIGKILL(OOM 杀掉):这类通常不产生 core,得看 dmesg 的 OOM 记录。
总结
core dump 排查链:ulimit -c unlimited 开开关 → 崩溃后拿到 core(或用 core_pattern 指定路径)→ gdb 可执行 core + bt 看堆栈 → 定位到源码某一行 → 修 + 回归。记住 ulimit 是临时的、core_pattern 也重启即失效,生产环境要提前把这两条写进配置。加 -g 编译,别用发布版二进制硬猜。
qidao123.com企服评测-应用市场 编辑提示 |