core dump未生成主因是三项配置未调优:ulimit -c 非零、/proc/sys/kernel/core_pattern 路径有效且可写、运行目录有写权限及磁盘空间充足;systemd服务需显式设limitcore=infinity。

core dump 为什么没生成?检查这三项配置
Linux 下 C++ 程序崩溃不产生 core 文件,90% 是因为系统级限制没放开。不是代码问题,是环境没配对。
-
ulimit -c必须设为非零值(如ulimit -c unlimited),否则内核直接丢弃 core;临时生效,建议加到~/.bashrc或启动脚本里 -
/proc/sys/kernel/core_pattern决定 core 文件写哪——默认可能指向pipe或空路径;用cat /proc/sys/kernel/core_pattern看一眼,想存当前目录就设成./core.%e.%p - 程序运行目录需有写权限,且磁盘不能满;如果用
systemd启动,它会重置ulimit,得在 service 文件里显式加LimitCORE=infinity
gdb 加载 core dump 的正确姿势
光有 core 文件不够,gdb 必须用**编译时的原始可执行文件**加载,否则符号全丢,堆栈全是 ??。
- 确认可执行文件没被 strip 过:
file ./myapp输出里含not stripped才行;若已 strip,只能靠带调试信息的版本(如myapp.debug)配合set debug-file-directory - 加载命令就是
gdb ./myapp core.12345,别漏掉可执行文件路径;进 gdb 后立刻输bt,看第一帧是不是你的函数 - 如果
bt显示no stack或地址乱跳,大概率是 ASLR 干扰——临时关掉:echo 0 | sudo tee /proc/sys/kernel/randomize_va_space(仅调试用)
signal(SIGSEGV, handler) 会阻止 core dump 吗?
会,但只在 handler 里没调 abort() 或 raise(SIGSEGV) 时才真阻止。默认行为被覆盖后,得手动补上。
- 注册自定义信号处理函数后,内核不再自动产生 core,除非你在 handler 里显式调用
abort()、raise(SIGABRT)或exit(128 + SIGSEGV) - 更稳妥的做法:handler 里记录日志 + 调
signal(SIGSEGV, SIG_DFL)再raise(SIGSEGV),把控制权交还给默认行为 - 注意:
sigaction比signal更可靠,尤其涉及SA_RESETHAND和SA_NODEFER标志位时
core dump 太大?按需裁剪而不是关掉
动不动几个 GB 的 core 不是必须接受的,Linux 提供了精细控制,关键在 /proc/[pid]/coredump_filter。
立即学习“C++免费学习笔记(深入)”;
- 默认值
0x33包含私有匿名映射和 ELF 文件映射,通常就足够定位问题;若只想保留堆栈和寄存器,设成0x01(仅私有匿名区) - 修改方式:
echo 0x01 > /proc/self/coredump_filter(进程启动前)或写入对应 pid 目录(需权限) - 注意:此设置只影响后续生成的 core,不影响已存在的;容器环境可能被 seccomp 或 cgroup 限制,得检查
docker run --ulimit core=-1:-1
真正麻烦的是多线程下信号触发时机和栈帧错位,这时候 core 里看到的不是崩溃点,而是 signal delivery 的中间状态——得结合 info threads 和 thread apply all bt 全局看。








