能直接用 gdb 加载 core 文件分析,前提是程序编译时带 -g 且未启用激进优化(如 -o2 以上),否则堆栈会出现 ?? 或无法定位行号;需确认 ulimit -c 非0、core_pattern 路径正确、可执行文件与 core 文件严格匹配同一版本。

能直接用 gdb 加载 core 文件分析,前提是程序编译时带 -g 且没开激进优化(比如 -O2 以上可能内联或删帧),否则堆栈里会看到大量 ?? 或无法定位行号。
确认 core 文件已生成且路径正确
很多问题其实卡在根本没生成 core 文件,或者生成了但找不到:
-
ulimit -c输出必须不是0;若为0,先执行ulimit -c unlimited - 检查
/proc/sys/kernel/core_pattern,默认是core,但可能被改成了带路径的格式(如/var/core/%e.%p);ls -l core*或find /var/core -name "*your_program*"更可靠 - 程序崩溃时当前工作目录不一定是你认为的那个目录——建议用绝对路径启动,或在崩溃前
pwd留痕
gdb 加载 core 的基本命令格式
语法固定:gdb <core></core>,两个路径都必须存在且权限可读:
- 可执行文件必须和崩溃时运行的是**同一个二进制**(哪怕只改一行再重编译,符号就对不上)
- 如果 core 是
core.12345,而程序叫myapp,且都在当前目录:gdb ./myapp ./core.12345 - 启动后立刻输
bt(即backtrace),看最顶上那一帧是不是你代码里的函数;如果不是,说明符号缺失或版本不匹配
无 -g 编译时怎么勉强看堆栈
Release 版本没调试信息,bt 会显示函数名但没有文件/行号,局部变量也全 <optimized out></optimized>:
- 用
objdump -t your_binary | grep "F .text"粗略看函数地址范围,再结合bt中的地址反查函数名 -
info registers查看崩溃时寄存器值,x/10i $rip反汇编崩溃点附近指令 - 更实用的办法:用同一份源码重新以
-g -O0编译一个 debug 版,然后gdb ./debug_binary ./core.release——GDB 允许混用,只要函数布局没大变,bt和list就能大致对上
常见陷阱:优化导致帧丢失或变量不可见
-O2 及以上级别会让 GDB 失去大部分上下文:
- 函数被内联后,
bt里看不到中间调用层,直接从main跳到崩溃点 - 局部变量被存在寄存器而非栈上,
print var返回<optimized out></optimized> - 解决方法不是“关所有优化”,而是加
-Og:GCC 官方推荐的“调试友好型优化”,保留完整调试信息,同时做轻量级优化(如常量传播、死代码消除) - 如果必须用
-O2,至少补上-fno-omit-frame-pointer,确保bt不至于完全断掉
真正难的不是命令怎么敲,而是确认你手上的 binary 和 core 是一对、且没被 strip 过;一旦符号错位,所有 bt 和 list 都只是幻觉。











