必须在malloc返回后、指针已赋值的断点处用x命令查看内存,否则地址不可知或无效;需确认p非零、禁用优化、指定正确单位格式(如x/1xb p),避免访问已释放或未映射内存。

直接用 x 命令查看,但必须在 malloc 返回后、指针变量已赋值的断点处操作,否则地址不可知或已被覆盖。
断点要设在 malloc 调用之后
不能在 malloc 函数内部打断点(除非你进到 libc 源码),而应在调用返回后的下一行设断点。例如:
char *p = malloc(32); // ← 断点设在这里的下一行 strcpy(p, "hello");
此时 p 已持有有效地址,GDB 才能读取它。常见错误是断点设太早(如刚进 main)或太晚(p 已被 free 或越界写坏)。
- 确认变量已赋值:执行
p p看是否输出非零地址,如$1 = 0x5555555592a0 - 避免优化干扰:编译时加
-O0 -g,否则p可能被寄存器优化掉,print p报No symbol "p" in current context - 若用
gcc -Og(如 CSAPP MallocLab 要求),需确保变量未被内联或提升,可临时加volatile强制保留
x/ 命令参数选错会导致数据错乱
x 不是“打印变量值”,而是按指定格式和单位解析内存。对 malloc 返回的原始地址,必须明确单位(b/h/w/g)和格式(x/d/c/s),否则看到的是拼接错误的字节。
- 查首字节内容(比如验证是否初始化为
0xbe):x/1xb p - 查前 4 个字(16 字节)十六进制:
x/4xw p - 查字符串内容(注意末尾是否有 \0):
x/s p - 查一个 int 类型字段:
x/dw p(w表示 word=4 字节,d是有符号十进制) - 误用
x/4x p(缺单位)会默认用w,但若你本意是看字节流,就会漏掉中间字节
地址本身可能合法,但内容不可读
即使 p 是有效堆地址,x 仍可能报 Cannot access memory at address 0x...。这不是命令写错,而是:
- 该地址所属页未映射(如
malloc失败返回NULL,但代码没检查就直接x/1xb p) - 堆块已被
free,glibc 将其标记为不可访问(尤其启用MALLOC_PERTURB_=1时) - ASLR 开启且你硬编码了旧地址(应始终用
p或&var动态获取) - 在
free(p)后还执行x/1xb p,属于未定义行为,GDB 可能拒绝读取
真正容易被忽略的,是 x 的“状态延续”机制:一旦你用过 x/4xw p,后续只输 x/8 就会自动沿用 xw 格式和单位——但你可能忘了上次是 xb,结果看到的仍是 4 字节宽的数据,误以为内容异常。


















