compare-memory命令可直接比对两块内存区域,语法为/LENGTH UNIT FROM-ADDR TO-ADDR,支持字节(b)、半字(h)、字(w)单位,不依赖源码和libc符号,但需地址合法且可访问。

用 compare-memory 命令直接比对两块内存区域
GDB 本身不提供类似 memcmp() 那样返回差值的函数,但内置的 compare-memory(简写 cmp)命令能逐字节比对两个地址范围,输出第一个不匹配的位置和差异字节数。它不依赖源码,只要目标进程可访问、地址合法就能用。
常见错误现象:直接在 GDB 里敲 memcmp(addr1, addr2, len) 会报错 Function 'memcmp' not defined —— 因为 GDB 默认不链接 libc 符号,且该函数是运行时库函数,不是调试器原生命令。
- 语法必须是:
compare-memory /LENGTH UNIT FROM-ADDR TO-ADDR,其中UNIT是单位(b字节、h半字、w字),LENGTH是数量(不是字节数) - 例如比对 32 字节:
compare-memory /32b 0x7fffffffe000 0x7fffffffe020 - 若地址不可读(如未映射、权限不足),GDB 会提示
Cannot access memory at address ...,此时需先确认目标地址是否属于当前进程的有效映射区(可用info proc mappings查) - 该命令不支持条件断点中嵌套调用,也不能在
print表达式里使用
用 x 命令手动导出再比对(适合小数据或无 compare-memory 的旧版 GDB)
某些精简版 GDB(如嵌入式交叉工具链里的)可能没编译进 compare-memory。这时得靠 x 拆解查看,再肉眼或脚本比对。
使用场景:调试栈上两个局部数组是否一致、验证 memcpy 是否正确拷贝、检查结构体 padding 是否被意外修改。
-
x/16xb &buf1和x/16xb &buf2分别以十六进制字节形式打印前 16 字节 - 想转成可复制的 hex 字符串,可用 Python 脚本辅助:
python -c "print(' '.join(f'{b:02x}' for b in bytes([0x11,0x22,0x33])))",但注意 GDB 内无法直接执行该命令 - 更稳的方式是用
dump binary memory先导出二进制片段:dump binary memory /tmp/buf1.bin 0x7fffffffe000 0x7fffffffe020,再用系统cmp或xxd工具比对文件 - 注意:
dump地址范围是 [start, end),end 必须大于 start,否则报错Invalid address
为什么不用 print + memcmp?
有人尝试在 GDB 里执行 print memcmp((void*)0x1000, (void*)0x2000, 64),结果失败。这不是 bug,而是设计限制:
- GDB 的
print只能调用目标进程已加载且符号可见的函数,而memcmp属于 libc,通常以 PLT 形式延迟绑定,GDB 无法在运行时安全解析并跳转 - 即使强制用
call(如call (int)memcmp(...)),也可能因寄存器状态不匹配、栈被破坏导致目标进程 crash 或行为异常 - 部分 libc 实现(如 musl)甚至把
memcmp做成内联汇编或宏,根本无符号可调 - 所以官方文档明确建议:内存比对优先用
compare-memory,而非模拟运行时函数调用
容易忽略的地址对齐与长度陷阱
比对结果不准,十有八九栽在这两点上。
-
compare-memory /16w 0x1000 0x2000看似比 16 个“字”,实际是比 16×4 = 64 字节(x86_64 下w是 4 字节),不是你想的 16 字节 - 若地址未按
UNIT对齐(比如用/8h但起始地址是奇数),GDB 可能静默截断或报错,不同版本行为不一致 - 用
info registers或info proc mappings确认地址确实落在可读内存段内,尤其注意 ASLR 启用后每次运行地址都变,硬编码地址极易失效 - 远程调试(gdbserver)时,
compare-memory仍有效,但速度受网络延迟影响,大块比对建议改用dump+ 本地工具
info proc mappings 确认地址合法,再严格按 compare-memory 的单位语义写参数,其余都是绕弯。


















