修改指针变量本身的值需用set $ptr = 新地址,改指向内容用set {type}addr = 值,改结构体嵌套指针需显式类型转换,三者层次不同易混淆。

直接修改指针变量本身的值(最常见)
指针变量本身是一个存储地址的变量,它在内存中有自己的位置。要改“指针指向哪”,本质是修改这个变量里存的地址值,而不是去动它指向的内容。
用 set 命令赋新地址即可,注意类型必须匹配:
-
set $ptr = 0x7fffffffe000—— 如果$ptr是char *或void *,GDB 通常能自动推导 -
set *(int **)ptr_addr = 0x12345678—— 若你只有指针变量的地址(比如从info registers rbp算出栈上偏移),需先解引用为二级指针再赋值 - 错误写法:
set *$ptr = 0x12345678—— 这改的是指针「指向的内容」,不是指针本身
修改指针所指向的内存内容(容易混淆)
这是另一个动作:不改变指针变量的值,只改它当前指向那块内存里的数据。用 set + 内存地址语法:
-
set {int}0x7fffffffe000 = 42—— 把地址0x7fffffffe000处的 4 字节设为整数 42 -
set {char[5]}0x7fffffffe000 = "hello"—— 写入字符串(注意结尾 \0) - 别用
set *$ptr = ...直接赋值,除非你确认$ptr已被 GDB 正确识别为指针类型;否则可能报错 “Cannot assign to this lvalue”
用 x 验证指针值是否真被改了
改完必须验证,因为 GDB 不会主动刷新符号表,有时显示旧值:
-
p/x $ptr—— 查看寄存器或 convenience variable 中的指针值(十六进制) -
x/1gx &ptr—— 查看指针变量ptr在栈/数据段中的实际存储值(g表示 8 字节,适配 64 位地址) - 如果
p $ptr和x/1gx &ptr结果不一致,说明你改的是 convenience var 而非真实内存,得用set *(type*)&ptr = ...显式写内存
结构体里嵌套指针的修改要小心类型
比如有 struct node { int val; struct node *next; };,想把 head->next 指向别处:
- 先确认类型:
ptype head->next,大概率是struct node * - 正确写法:
set *(struct node **)&head->next = new_node_addr - 错误写法:
set head->next = new_node_addr—— GDB 可能拒绝,因字段访问不支持直接赋值 - 更稳妥:用
set {struct node *}head->next = new_node_addr(GDB 7.12+ 支持)
set 就会静默失败或改错地方。


















