必须加-g编译,否则GDB无法定位源码、读取变量、设置断点;漏-g或用-O2会导致“No symbol table is loaded”、list为空、print报错、单步跳行错乱,-O2/-O3还会因内联和优化使源码与汇编脱节。

必须加 -g 编译,否则 GDB 无法定位源码、读取变量、设置断点——这不是可选项,是硬性前提。
编译时漏掉 -g 或用了 -O2 会怎样
现象很直接:No symbol table is loaded. Use the "file" command;或者能进 GDB,但 list 显示空、print 报 Cannot access memory、单步跳行完全对不上源码。
-
-g是生成调试符号的开关,没有它,GDB 就像没带地图开车 -
-O2/-O3会内联函数、删临时变量、重排逻辑,导致你看到的汇编和源码脱节;调试时优先用-O0,必要时用-Og - 多文件编译要给每个
.cpp都加-g,只给主文件加没用 - 如果用 CMake,确认
set(CMAKE_BUILD_TYPE Debug),否则默认是RelWithDebInfo或Release,可能缺调试信息
break 断点设不生效的常见原因
不是命令输错了,而是环境或代码本身卡住了断点生效。
- 在内联函数(
inline)、模板实例化函数、或被-O2内联掉的函数里设break func_name,大概率失败;改用break 文件名:行号 - 动态库(
.so)没带-g编译,或者没加载符号:运行中执行sharedlibrary查看是否已加载,没加载就add-symbol-file - 程序还没加载完就设断点(比如在
main之前),GDB 可能忽略;可用break _start或break *0x地址硬断 - 条件断点写错语法:
break 15 if i > 10正确,break 15 if (i > 10)在旧版 GDB 会报错
崩溃后怎么看清真正出问题的位置
光靠 bt 不够,尤其涉及 STL、线程、异常时,调用栈常被截断或显示 ??。
立即学习“C++免费学习笔记(深入)”;
- 崩溃后第一件事是
bt full,而不是只敲bt—— 它会同时打印寄存器和局部变量值 - 如果栈帧里有
std::vector::at或__gnu_cxx::__verbose_terminate_handler,基本就是越界或未捕获异常,接着frame 1再print相关容器/指针 - 多线程下崩溃,
info threads看哪个线程挂了,thread N切过去再bt,别只看主线程 - core dump 分析时,确保启动 GDB 时带 core 文件:
gdb ./app core,不是gdb ./app后再core-file core(后者可能符号不全)
真正难的不是记住命令,而是判断「此刻该信哪一行输出」:GDB 显示的行号可能是优化后的、变量值可能是寄存器缓存的、调用栈可能被异常处理机制压平。动手前先确认编译参数,崩溃后先看 bt full 和当前线程,比盲目单步更省时间。


















