ulimit -c设为0时内核直接跳过core写入流程,不触发任何生成逻辑;需设为unlimited或正整数,并配合core_pattern路径权限、dumpable状态及调试符号等条件才能成功生成。

ulimit -c 为什么设成 0 就不生成 core 文件
Linux 默认把 ulimit -c 设为 0,这是内核级硬限制:只要这个值是 0,无论程序怎么崩溃、/proc/sys/kernel/core_pattern 配得多好,内核直接跳过写 core 的逻辑。不是“写失败”,是根本不会触发写入流程。
实操建议:
- 临时生效:运行
ulimit -c unlimited(或指定字节数如ulimit -c 2097152表示 2MB 上限) - 注意该命令只影响当前 shell 及其子进程,用
bash -c 'ulimit -c; ./a.out'测试时容易误判——得在同个 shell 里先设再跑 - 若用 systemd 启动服务,
ulimit不生效,得改 service 文件里的LimitCORE=或LimitCORE=infinity
core_pattern 设置不对,文件名和路径会出什么问题
/proc/sys/kernel/core_pattern 决定 core 文件写哪、叫什么。默认可能是 core,意味着它会尝试写进当前工作目录——而很多程序(尤其是 daemon)启动时工作目录是 / 或 /root,普通用户没权限写入,结果静默失败。
常见错误现象:
立即学习“C++免费学习笔记(深入)”;
- 明明
ulimit -c unlimited了,但崩溃后找不到core文件 - 发现
/var/log/messages里有kernel: core_pattern: failed to exec ... permission denied(如果你用了管道模式)
推荐做法:
- 简单可靠:用绝对路径 + % 命名模板,例如
echo '/tmp/core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern - 确保目标目录存在且所有用户可写(
/tmp通常满足),避免权限问题 - 别轻易用
|/usr/lib/systemd/systemd-coredump这类管道模式,除非你真需要 coredumpctl,否则多一层依赖就多一个失败点
程序自己调用 prctl(PR_SET_DUMPABLE, 0) 会导致 ulimit 失效
有些程序(比如 setuid 程序、某些安全加固的 daemon)会在启动时主动关闭 core dump 能力,通过 prctl(PR_SET_DUMPABLE, 0)。这时即使 ulimit -c unlimited 和 core_pattern 都正确,也绝不会生成 core 文件。
验证方式:
- 崩溃前检查:
cat /proc/$(pidof your_program)/status | grep Dumpable,输出0就是被禁了 - 临时绕过(仅调试):用
sudo sysctl kernel.dmesg_restrict=0并确认没有 SELinux/AppArmor 拦截,但更稳妥的是改源码或启动参数禁用该 prctl 调用 - 注意:glibc 的
__libc_enable_secure()会自动触发这个行为,所以 setuid 程序默认 dumpable = 0,不能靠 ulimit 拉回来
用 GDB 直接加载 core 文件时提示 No symbol table is loaded
这不代表 core 没生成成功,而是你没用带调试信息的二进制。core 文件本身只存内存镜像,符号、变量名、行号全靠原程序的 debug info(通常是 .debug_* section 或分离的 .debug 文件)。
排查步骤:
- 确认编译时加了
-g(g++ -g -o app app.cpp),且没用strip过 - 用
file your_binary看输出是否含with debug_info;用readelf -S your_binary | grep debug看有没有调试节 - 如果用了
-grecord-gcc-switches或分离 debug 文件,GDB 需要能自动找到它(路径需匹配build-id或配置set debug-file-directory)
core 文件生成只是第一步,能不能真正用来定位 bug,取决于你手里那个二进制是不是“完整版”。很多人卡在这一步,反复检查 ulimit 却忘了编译选项。


















