在GDB中用print查看局部变量需确保当前停在该变量作用域内且编译时使用-O0 -g;若变量被优化则报“No symbol”,可用::或'file'::指定作用域,print/x ptr与print/x *ptr含义不同,查内存块应优先用x命令。

gdb 中用 print 查局部变量,但要注意作用域和优化干扰
局部变量在函数栈帧内,print 能直接显示值,前提是当前停在该变量可见的作用域里(比如函数内部、循环块中)。如果编译时用了 -O2 或更高优化等级,GCC 可能会把变量完全优化掉——此时 print var 会报错 No symbol "var" in current context。必须用 -O0 -g 重新编译才能稳定调试。
常见操作:
- 停在断点后,直接输入
print x查整型变量x的十进制值 - 用
print/x x显示十六进制(注意斜杠是分隔符,不是路径) - 对数组首元素取地址再打印:
print/x &arr[0],确认它是否在栈上 - 若变量名被遮蔽(如外层同名变量),可用
print ::x强制访问全局,或print 'filename.cpp'::x指定文件作用域
print/x 看指针本身和它指向的内存,写法完全不同
print/x ptr 打印的是指针变量存储的地址值(比如 0x7fffffffe420);而 print/x *ptr 才是解引用,读取该地址处的内存内容。新手常混淆这两者,结果看到“地址正常”就以为指针没问题,其实它可能指向已释放的栈帧或 nullptr。
关键区别:
-
print/x buf→ 输出0x7fffffffe3f0(指针值) -
print/x *buf→ 输出0x61(假设buf是char*,且首字节为'a') -
print/x *(int*)buf→ 强制按int解引用,输出 4 字节整数(需确保内存对齐且可读) - 若解引用非法地址(如
*((int*)0)),gdb 会报Cannot access memory at address 0x0,这不是程序崩溃,只是 gdb 读失败
查看连续内存块:用 x 命令比 print 更可靠
print 对数组或结构体只能展开一层,且格式固定;真正要看一串内存(比如缓冲区、字符串原始字节),得用 x(examine)命令。它的语法是 x/[n][f][u] addr,其中 n 是数量、f 是格式(x 十六进制/d 十进制/s 字符串)、u 是单位(b=1字节/h=2字节/w=4字节/g=8字节)。
实用组合:
-
x/10xb &arr[0]→ 查 10 个字节的十六进制(适合看 raw buffer) -
x/5dw ptr→ 从ptr开始读 5 个 4 字节整数(w表示 word) -
x/s str_ptr→ 当作 C 字符串打印(自动停在\0) -
x/20c ptr→ 打印 20 个字符的 ASCII 值(含不可见字符)
注意:x 不检查类型安全,也不会触发程序异常——哪怕地址无效,gdb 顶多显示 Cannot access memory,不影响被调进程。
struct 和类成员变量要避免直接 print/x this->member
对 C++ 成员变量,直接 print/x obj.member 或 print/x this->member 大部分时候可行,但如果成员是私有、或涉及虚函数表偏移、或对象内存布局复杂(比如多重继承),gdb 可能解析错误或显示 。更稳妥的方式是先 info registers 确认 this 地址,再用 x 手动偏移查看。
例如:
-
info symbol $rdi(x86_64 下this通常在%rdi)可确认对象起始地址 -
ptype MyClass查结构体布局和成员偏移 - 若知道
int val在偏移 8 字节处,可用x/wx $rdi+8直接读 - 对
std::string这类内部指针封装的类型,print s.c_str()比print s更容易看到实际内容
调试 C++ 时,gdb 对模板实例化、内联函数的支持依赖于调试信息质量,-g3 比 -g 更好,但依然可能漏掉某些临时对象的生命周期信息。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











