要查看非当前栈帧的局部变量,需先用 frame n 切换到目标帧再执行 info locals;若不切换帧,可用 print $n::variable_name 直接访问。

用 frame 切到目标栈帧再查 info locals
GDB 默认只显示当前栈帧(最顶层函数)的局部变量,想看上层或下层函数里的变量,必须先手动切换栈帧。比如你执行 bt 看到有 4 层调用,而你想查第 2 层(#2)里定义的 buf,就不能直接 p buf——它大概率报错 No symbol "buf" in current context。
正确做法是:
- 运行
bt或bt full确认目标帧编号(如#2) - 执行
frame 2(或简写f 2),GDB 会把上下文切过去,并自动显示该帧的源码行和寄存器状态 - 再执行
info locals,就能列出这一层所有可见的局部变量及其值 - 如果变量名有歧义(比如多层都有
i),可加作用域限定:p 'func_name'::i
print 直接访问某帧变量要带帧号前缀
不想切帧也能查,但语法稍严格:GDB 支持在 print 时显式指定栈帧,格式是 print $n::variable_name,其中 n 是 bt 输出的帧编号。
例如:
-
bt显示:#0 func_a() at a.c:10,#1 func_b() at b.c:5,#2 main() at main.c:12 - 你想查
main里定义的argc,就输p $2::argc - 注意:这个写法只对局部变量有效;全局变量或静态变量不用帧号,直接
p argc即可 - 如果变量是结构体成员,仍需解引用:
p $1::config->timeout
为什么 info locals 有时啥也不显示?
常见原因不是命令错了,而是编译优化或符号缺失:
- 没加
-g编译:GDB 根本看不到变量名,info locals必然为空——确认你用的是gcc -g或clang -g编译的可执行文件 - 开启了
-O2及以上优化:编译器可能把变量分配到寄存器、内联掉函数、甚至完全删掉未使用的变量。此时即使有-g,info locals也可能只显示部分变量,或显示<optimized out></optimized> - 变量作用域已结束:比如你在
if块末尾断点,块内定义的变量在语法上已不可见,GDB 不会列出 - 调试信息不完整:某些 C++ 模板实例化或内联函数可能导致局部变量符号丢失,这时得靠
x命令结合栈地址硬查
查不到变量时,用 x 和寄存器推地址是最后手段
当 info locals 失效且你又知道变量大概在栈上的偏移(比如从 IDA 或反汇编看出 rbp-0x28),就得手动读内存:
- 先
info registers rbp拿到当前帧的基址 - 算出变量地址:比如
rbp是0x7fffffffe2a0,偏移-0x28,那地址就是0x7fffffffe278 - 用
x/10xw 0x7fffffffe278查 10 个字(4 字节)的十六进制内容 - 若变量是字符串,改用
x/s 0x7fffffffe278;若是 double,用x/1fg(g表示八字节) - 注意:这种操作依赖你对栈布局和 ABI 的理解,容易因帧切换、寄存器重用而出错
真正麻烦的从来不是命令记不住,而是看到 <optimized out></optimized> 还硬试 print,或者在没 -g 的二进制里反复敲 info locals。先确认编译参数和优化等级,比背一百条 GDB 命令都管用。











