core dump 文件默认在程序运行时的工作目录,名为 core,但实际路径由 /proc/sys/kernel/core_pattern 决定;若该文件内容以 |/usr/lib/systemd/systemd-coredump 开头,则需用 coredumpctl 查看和导出。

core dump 文件在哪,怎么确认它真被生成了
Linux 默认可能根本没开 core dump,所以第一步不是分析,而是确认你有东西可看。先检查 ulimit -c,输出是 0 就代表被禁用了;临时打开用 ulimit -c unlimited,但要注意这仅对当前 shell 及其子进程生效。
生成的 core 文件默认叫 core,通常落在程序执行时的工作目录(不是源码目录,也不是 /tmp),但实际路径受 /proc/sys/kernel/core_pattern 控制。常见坑是:程序在 systemd 下跑,systemd 会拦截 core dump 并转给 systemd-coredump,此时你得查 coredumpctl list,而不是满硬盘找 core 文件。
- 用
cat /proc/sys/kernel/core_pattern看当前策略 - 若输出类似
|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %e,说明走 systemd 管理,别去文件系统里瞎翻 - 手动测试是否能生成:运行
kill -SEGV $$(对自己 shell 发段错误),再看ulimit -c非零且当前目录有没有新core
用 gdb 打开 core dump 看崩溃点最直接
有 core 文件 + 对应的原始可执行文件(必须是同一构建产物,带调试符号更好),就能定位到具体哪行代码崩的。gdb ./myapp core 进去后,bt(backtrace)是第一指令,它显示函数调用栈,最顶上那帧就是崩溃现场。
容易忽略的是符号问题:如果程序是 release 编译且 strip 过,bt 只能看到函数地址,看不到文件名和行号。这时候要么重编译加 -g,要么用 readelf -S ./myapp | grep debug 确认调试信息是否还在。
-
info registers查看崩溃时各寄存器值,尤其rip/pc和rsp,能辅助判断是空指针还是栈溢出 -
frame 0后跟list,可显示崩溃行附近源码(需有调试信息) - 若 core 是 systemd 生成的,用
coredumpctl dump -o core myapp先导出成传统 core 文件再用 gdb
没有源码或调试信息时,objdump + addr2line 能救急
生产环境常遇到只有 stripped 二进制和 core 的情况。这时靠 gdb 只能看到汇编,但至少能知道崩在哪个函数偏移处。先用 gdb ./myapp core,执行 bt,记下最上面那行的地址(比如 #0 0x0000555555556123 in ?? ())。
这个地址是虚拟内存地址,要映射回代码位置,得结合程序的加载基址。用 readelf -l ./myapp | grep LOAD 找第一个 LOAD 段的 Virtual Address(比如 0x555555554000),然后算偏移:0x0000555555556123 - 0x555555554000 = 0x2123。再用 addr2line -e ./myapp 0x2123 查源码行——前提是编译时没关 -g,否则只能靠 objdump -d ./myapp | grep -A10 -B10 '2123$' 看附近汇编逻辑。
-
gdb里info proc mappings可查实际加载地址,比 readelf 更准(尤其开了 ASLR 时) -
addr2line输出??表示没调试信息,不是命令用错了 - 若程序是动态链接的,崩溃可能在 so 里,得用
info sharedlibrary看 so 加载地址,再对齐偏移
systemd-coredump 日志里藏了不少线索
很多用户卡在“找不到 core 文件”,其实日志里早写了原因。运行 coredumpctl info myapp,输出里 Signal(如 SIGSEGV)、Executable、Stack trace(如果有符号)都直接可用。更关键的是 Coredump 字段,它告诉你这个 core 存哪(通常是 /var/lib/systemd/coredump/ 下带时间戳的压缩文件)。
systemd 默认把 core 压缩存档,所以不能直接 gdb,得先解压:zcat /var/lib/systemd/coredump/core.myapp.*.xz > core。另一个常被忽略的点是:coredumpctl list 显示的 PID 是崩溃时的进程 ID,但如果你重启过机器,旧 core 可能已被自动清理(看 /etc/systemd/coredump.conf 的 MaxUse 和 KeepFree)。
- 查历史崩溃:用
coredumpctl --since="2024-05-01" list限定时间范围 - 想永久保存所有 core,改
/etc/systemd/coredump.conf中Storage=external并确保/var/lib/systemd/coredump有足够空间 -
coredumpctl debug myapp会直接启动 gdb 并加载对应 core 和二进制,省一步手动操作
事情说清了就结束。真正难的不是看懂 bt,而是确认你手上的 binary、core、debug info 三者版本完全匹配——差一个 commit,地址就对不上。










