c++的DWARF调试信息是什么? (深入理解GDB)
技术百科
尼克
发布时间:2026-01-17
浏览: 次 DWARF 是标准化调试信息格式,GDB 依赖其解析变量、调用栈和源码映射;它独立于编译器和语言,嵌入在目标文件中,与符号表(.symtab)功能不同。
什么是 DWARF,它和 GDB 有什么关系?
DWARF 是一种标准化的调试信息格式,不是 C++ 语言特性,也不是编译器私有产物。GDB 能识别变量名、调用栈、源码行号、结构体内存布局,全靠目标文件(.o)或可执行文件里嵌入的 DWARF 数据。GCC/Clang 默认在 -g 下生成 DWARF v4/v5,GDB 依赖这些数据做符号解析和内存映射。
怎么确认你的二进制里真有 DWARF?
常见错误是以为加了 -g 就万事大吉,但链接时可能被 strip 掉,或用了 -s。验证方法很简单:
readelf -w ./a.out | head -20 # 或更直接: file ./a.out # 输出含 "with debug_info" 才算有效 # 若看到 "stripped",说明 DWARF 已丢失,GDB 将无法显示变量、无法步进源码
-
objdump -g可看简化版调试条目,适合快速扫一眼是否有DW_TAG_subprogram(函数)或DW_TAG_variable - 如果用
编译,DWARF 仍在,但变量可能被优化掉(
gcc -g -O2
optimized out),这不是 DWARF 缺失,而是编译器没给它留寄存器/栈位置
为什么 GDB 有时显示不出局部变量或内联函数?
这通常不是 GDB 的 bug,而是 DWARF 描述和实际代码不匹配:
- 内联函数默认不生成独立
DW_TAG_subprogram,除非加__attribute__((used))或编译时用-ginline-points(GCC)让 DWARF 记录内联点 - 局部变量若被分配到寄存器且未 spill 到栈,DWARF 可能只写
DW_OP_regX;GDB 在某些架构(如 ARM64 中断上下文)可能读不到该寄存器当前值 - 使用
-frecord-gcc-switches可让 DWARF 存编译参数,有助于排查“为什么这个 struct 成员 offset 不对”之类问题
DWARF 和符号表(.symtab)是两套东西
很多人混淆 nm ./a.out 能看到的符号和 GDB 能用的变量。关键区别:
-
.symtab只存函数/全局变量的地址和名字(比如main、global_counter),没有类型、作用域、行号信息 - DWARF 提供
main的参数类型、每行对应哪段机器码、std::vector的size()成员函数在哪——这些.symtab完全不记录 -
strip --strip-unneeded会删.symtab但保留 DWARF;strip --strip-debug才删 DWARF——别用错命令
真正卡住调试的,往往不是“找不到符号”,而是 DWARF 描述的变量生命周期和实际寄存器分配对不上,这时候得看 info registers 和 maint info dwarf 对比验证。
# ai
# 是一种
# 很多人
# 用了
# 找不到
# 不出
# 很简单
# c++
# int
# 区别
# 为什么
# 架构
# 栈
# 行号
# bug
# 成员函数
# 结构体
# 作用域
# Struct
# 万事大吉
# switch
# 不上
# 局部变量
# 全局变量
# 步进
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么清理C盘系统错误报告_Win11清理
- 如何高效识别并拦截拼接式恶意域名 spam
- php485返回数据不完整怎么办_php485数据
- Win10系统更新错误0x80240034怎么办
- windows 10应用商店区域怎么改_windo
- Flask 表单数据通过 SMTP 发送邮件的完整
- php打包exe后无法写入文件_权限问题解决方法【
- php8.4如何调用com组件_php8.4win
- MAC的“接续互通”功能无法使用怎么办_MAC检查
- Win11怎么检查TPM2.0模块_Windows
- Golang如何遍历目录文件_Golang fil
- 如何使用Golang操作指针变量_Golang解引
- Win10怎么关闭自动更新错误弹窗_Win10策略
- 如何在Golang中指定模块版本_使用go.mod
- Windows10电脑怎么查看硬盘通电时间_Win
- ACF 教程:如何正确更新嵌套在多层 Group
- Windows怎样关闭Edge新标签页广告_Win
- Win11麦克风没声音怎么设置_Win11麦克风权
- 静态属性修改会影响所有实例吗_php作用域操作符下
- php485在macos下怎么配置_php485
- php订单日志怎么记录物流_php记录订单物流变更
- 如何使用Golang实现路由分组管理_Golang
- Win11怎么设置任务栏图标大小_Windows1
- Mac如何开启夜览模式_Mac护眼模式设置与定时
- 如何使用Golang构建简易投票统计功能_Gola
- Win11怎么查看硬盘型号_Windows 11检
- Python迭代器生成器进阶教程_节省内存与懒加载
- php8.4xdebug无法调试怎么办_php8.
- 如何使用Golang实现Web表单数据绑定_自动映
- VSC怎样用终端运行PHP_命令行执行脚本的步骤【
- Win11怎么关闭系统声音_Win11系统提示音静
- Golang如何实现基本的用户注册_Golang用
- Python脚本参数接收_sys与argparse
- 如何在 Laravel 中通过嵌套关联关系进行 o
- 如何在 Django 中修改用户密码后保持会话不丢
- Golang如何避免指针逃逸_Golang逃逸分析
- 短链接怎么自定义还原php_修改解码规则适配需求【
- 如何在Golang中捕获结构体方法错误_Golan
- 如何在Golang中处理数据库事务错误_回滚和日志
- Windows 11如何开启文件夹加密(EFS)_
- c++如何打印函数堆栈信息_c++ backtra
- win11如何清理传递优化文件 Win11为C盘瘦
- Win11如何更改用户账户文件夹名称 Win11修
- 如何使用Golang实现聊天室消息存档_存储聊天记
- Windows系统文件被保护机制阻止怎么办_权限不
- 如何使用Golang实现文件追加操作_向已有文件追
- Win10怎么创建桌面快捷方式 Win10为应用创
- php中::能用于接口静态方法吗_接口静态方法调用
- MySQL 中使用 IF 和 CASE 实现查询字
- 微信JSAPI支付回调PHP怎么接收_处理JSAP


QQ客服