core dump 是诊断偶发崩溃的唯一事后手段,需确保 ulimit、systemd/docker 配置、core_pattern、目录权限、调试符号及验证流程全部正确,否则 core 文件将静默丢失。

偶发性崩溃最难办的不是崩溃本身,而是它不配合复现——你改完代码跑十次没事,上线后隔两天又崩一次。Core Dump 是唯一能让你“事后抓现行”的手段,但前提是它真被生成、真能定位、真包含有效信息。
ulimit -c unlimited 不等于 core 一定生成
很多开发者执行了 ulimit -c unlimited 就以为万事大吉,结果程序崩了却找不到 core 文件。根本原因在于:这个设置只对当前 shell 及其子进程生效,且会被 systemd、容器、或启动脚本覆盖。
- 检查是否真正生效:
ulimit -c输出必须是unlimited或一个大于 0 的数字,不能是0 - 如果程序由 systemd 启动,需在 service 文件中加
LimitCORE=infinity,否则 ulimit 设置无效 - Docker 容器默认禁用 core dump,启动时要加
--ulimit core=-1:-1 - 确认内核允许写入:
cat /proc/sys/fs/suid_dumpable应为2(尤其当程序带 setuid 权限时)
core_pattern 决定你能不能快速找到文件
默认的 core 文件名没有任何上下文,多进程并行时极易混淆。不设 /proc/sys/kernel/core_pattern,等于把线索扔进垃圾桶。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 推荐设置:
echo '/var/log/coredumps/core.%e.%p.%t' | sudo tee /proc/sys/kernel/core_pattern -
%e是程序名,%p是 PID,%t是时间戳(秒级),三者组合可避免重名且便于按时间/进程筛选 - 确保目标目录存在且进程有写权限(如
/var/log/coredumps需chmod 755并归属运行用户) - 避免用
%h(主机名)或%u(UID)——它们在容器或动态环境中不稳定
gdb 加载 core 必须带原可执行文件
单独打开 core 文件毫无意义。GDB 需要原始可执行文件(含 -g 编译的调试符号)才能把内存地址映射回源码行号。
- 正确命令是:
gdb ./my_program /var/log/coredumps/core.my_program.12345.1727751234 - 错误做法:
gdb -c core.xxx—— 这种语法早已弃用,且无法加载符号,bt显示全是 ?? - 如果提示
No symbol table is loaded,说明可执行文件没带调试信息,重新用g++ -g -O0编译(生产环境建议保留.debug_*段或分离符号) - 进入 gdb 后第一件事是
bt full,而不是只看bt——full能显示局部变量值,对判断空指针、越界、竞态至关重要
偶发崩溃大概率是内存破坏,单靠 backtrace 不够
段错误(SIGSEGV)只是症状,真正的问题常发生在几十行甚至几百行代码之前:野指针释放后重用、堆缓冲区溢出、use-after-free、未初始化指针。backtrace 只告诉你“倒下的地方”,不告诉你“谁推的”。
- 先用
info registers看崩溃时rip和rdi/rsi/rax值,确认是否访问了明显非法地址(如0x0、0xfffffffffffffffe) - 用
x/10gx $rsp查看栈顶附近内存,常能发现被踩坏的返回地址或局部变量 - 若怀疑堆问题,用
heap命令(需安装glibc-utils)或malloc_info查看分配状态 - 终极手段:在开发环境用
AddressSanitizer重新编译运行,它能直接报出内存破坏的第一现场,比 core dump 高效十倍
最易被忽略的一点:偶发崩溃的 core 文件可能因磁盘满、权限错、路径不存在而静默失败。上线前务必用 kill -ABRT $(pidof my_program) 主动触发一次,验证整个链路(ulimit → core_pattern → 目录权限 → 文件生成 → gdb 可读)是否真实通路。否则真崩了,你还在找那个根本没生成的文件。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










