You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GDB中examine与print命令返回同一内存地址不同值的原因排查

为什么GDB的x和p命令对同一内存地址返回不同值?

这个问题我之前调试时也碰到过,核心原因是**x(examine)和p(print)命令的设计逻辑完全不同**:一个是直接读取指定大小的内存字节,一个是按数据类型来解析内存,哪怕指向同一个地址,处理方式也有本质区别。

先搞懂两个命令的核心差异

x命令:纯内存视角,按指定单元大小读取

x是专门用来“检查内存原始内容”的命令,它完全听你的指令读取指定大小的内存块。格式是x/<n/f/u>,其中u就是内存单元大小:

  • b:1字节(byte)
  • h:2字节(半字,halfword)
  • w:4字节(字,word,多数架构下的默认值)
  • g:8字节(八字节,giant)

如果你没指定u,GDB会用当前设置的默认单元大小(可以用show x命令查看)——比如你例子里的x/d $ebp-0x1c应该是默认按字节读取,所以只拿了地址处的1字节数据。

p命令:类型视角,按变量类型(或默认类型)解析

p命令是用来“打印变量值”的,当你直接解引用一个裸地址(比如*0xffffd10c)时,GDB必须先确定这个地址指向的是什么类型的数据:

  1. 如果这个地址对应程序里的某个变量(比如局部变量、全局变量),GDB会直接用该变量的类型来读取数据(比如变量是short就读2字节,int读4字节)。
  2. 如果没有符号信息,GDB会默认把它当成int*来解引用(32位架构下读4字节,64位读8字节)。

你的例子里到底发生了什么?

看你第一次的调试输出:

(gdb) x/d $ebp-0x1c
0xffffd10c: 126
(gdb) p *0xffffd10c
$1 = 382
  • x/d读取的是0xffffd10c处的1字节:0x7e(十进制126)。
  • p *0xffffd10c读取的是该地址处的2字节(因为GDB通过符号信息知道这里是short类型的变量):0x017e(十进制382,低字节是0x7e,高字节是0x01)。

再看你更新的测试:

(gdb) p/x *0xffffd110
$5: 0x9c9
(gdb) x/x $ebp-0x18
0xffffd110: 0xc9
  • x/x读取的是0xffffd110处的1字节:0xc9。
  • p/x *0xffffd110读取的是2字节:0x09c9(也就是输出里的0x9c9,省略了前导0),其中0xffffd110是低字节0xc9,下一个地址0xffffd111是高字节0x09。

怎么让两个命令返回一致的结果?

很简单,显式匹配两者的读取大小/类型就行:

方法1:给x命令指定匹配p的单元大小

如果p读的是2字节的short类型,那给x加h参数指定半字大小:

x/dh $ebp-0x1c  # h表示读取2字节数据

这样读取的结果就会和p *0xffffd10c完全一致。

方法2:给p命令显式指定类型

如果你想让p只读取1字节(和x的默认字节读取一致),可以强制把地址转换成char*类型:

p/x *(char*)0xffffd110

这样输出的就是0xc9,和x/x $ebp-0x18的结果一致。

额外技巧:查看GDB的默认设置

用show x命令可以查看x命令的默认格式和单元大小,方便你排查问题:

show x

输出大概是这样的:

The output format for the examine command is "x".
The default number of units to display is 1.
The default unit size is "byte".

内容的提问来源于stack exchange,提问作者Mr.SrJenea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:45:13