-g 是 clang 编译生成调试信息的必要参数,但默认 dwarf 版本因平台而异;linux 用 dwarf,macos 默认 dwarf-2,推荐显式指定 -gdwarf-4/5;需避免 strip 删除调试段,并配合 -o0 或 -og 保证调试可靠性。

clang 编译时加 -g 就行,但不同调试格式影响很大
直接加 -g 能生成调试信息,但默认行为因平台和 Clang 版本略有差异。Linux 上通常生成 DWARF 格式,macOS(Xcode 工具链)默认用 DWARF-2,而较新版本支持 DWARF-4/5。不指定格式时,-g 一般等价于 -gdwarf-2,但调试器兼容性可能受限。
-
-g:最简写法,适合快速调试,但某些高级调试功能(如 inlined 函数追踪、复杂类型展开)在旧 DWARF 版本下不可靠 -
-g -gdwarf-4或-g -gdwarf-5:显式指定新版 DWARF,LLDB 和 GDB 10+ 都支持,推荐用于 C++20 项目或需要完整类型信息的场景 -
-gline-tables-only:只生成行号映射,体积小、编译快,适合 CI 中做基本栈回溯,但无法查看变量、不能单步进函数体
链接阶段也要保留调试信息,别被 strip 掉
即使编译时加了 -g,如果后续链接或安装流程执行了 strip,调试信息就彻底丢了。Clang 默认不会 strip,但构建系统(如 CMake 的 install(FILES ... RENAME ...))或打包脚本常悄悄干这事。
- 检查最终可执行文件是否含调试段:
file your_program输出里有 “with debug_info” 才算成功 - 验证符号存在:
llvm-readobj --sections your_program | grep debug应看到.debug_info、.debug_line等段 - CMake 用户注意:
set(CMAKE_BUILD_TYPE Debug)仅控制优化级别,-g需额外通过set(CMAKE_CXX_FLAGS_DEBUG "$CMAKE_CXX_FLAGS_DEBUG -g")显式补上
调试信息和优化等级冲突,-O0 最稳妥
-g 和 -O2 可以共存,但变量被优化掉、函数被内联、控制流被重排后,GDB/LMDB 单步会跳来跳去,print var 可能报 “Cannot access memory at address …”。这不是 Clang 的 bug,是优化本身的副作用。
Clang 22.1.3 Windows 64 位历史版本安装包,适合旧项目兼容、LLVM/Clang 工具链回退、编译行为对比、链接问题复现和 C/C++ 构建环境维护。
- 开发调试阶段优先用
-O0 -g:保证源码与指令一一对应,变量始终可读 - 必须测优化行为时,用
-O2 -g -fno-omit-frame-pointer:避免帧指针被删,让栈回溯更可靠 - Clang 14+ 支持
-Og:专为调试设计的优化等级,平衡性能与可观测性,比-O0快,又比-O2更友好
常见错误:用了 -g 却看不到源码,其实是路径没对上
GDB/LLDB 查找源文件依赖编译时记录的绝对路径。如果你在容器里编译、宿主机调试,或用了构建目录隔离(如 build/),调试器找不到 /home/user/project/src/main.cpp 就只能显示汇编。
- 用
-fdebug-prefix-map=OLD=NEW重写路径,例如:clang -g -fdebug-prefix-map=/tmp/build/=./ -o app main.cpp - 或者编译时用相对路径:在源码根目录运行
clang -g -c -o main.o main.cpp,避免绝对路径写死 - LLDB 用户可临时修复:
settings set target.source-map /tmp/build/ ./
调试信息本身没问题,只是路径断了——这是最常被当成“-g 不生效”的真凶。










