Delve调试时变量地址需显式取址:普通变量用p &v,指针变量用p uintptr(v);panic定位需禁用内联编译并用bt查倒数第二帧;指针比较用p uintptr(p1) == uintptr(p2);CGO地址差异因格式不同,统一用p printf("%p", uintptr(ptr))对齐。

delve 调试时看不到变量的内存地址?
默认 print 或 p 命令只显示指针指向的值,不是地址本身。想看地址得显式取址——哪怕它本来就是个指针。
- 用
p &v看变量v的地址(v是普通变量) - 用
p v看指针变量v的值(即它存的地址),但输出是十六进制数值,不带0x前缀,容易误以为是值 - 更可靠的是
p (*runtime.PanicError)(v)这类强制类型转换反而会失败;正确做法是p uintptr(v)把指针转成整数再打印 - 在 delve 1.21+ 中,
pp v(pretty print)有时会同时显示地址和内容,但不可依赖——它取决于类型是否被识别为“可解引用”
nil 指针 panic 时,dlv 怎么定位到具体哪行解引用了空指针?
Delve 启动时加 -r 参数能自动在 panic 处中断,但关键是要让 panic 栈完整、不被优化掉。
- 编译时禁用内联:
go build -gcflags="-l" -o main main.go,否则panic: runtime error: invalid memory address的栈可能跳过实际解引用点 - 运行 dlv:先
dlv exec ./main,再run,panic 后直接用bt(backtrace)看调用链 - 重点看倒数第二帧:最后一帧通常是
runtime.panicmem,上一帧才是你代码里写ptr.field或*ptr的地方 - 如果
bt显示某行是???,说明该函数被内联或符号缺失——重编译并确认没加-ldflags="-s -w"
怎么确认两个指针是否指向同一块内存?
不能靠 == 直接比较指针变量(Go 中允许,但 delve 里不支持表达式求值),得转成整数比对。
- 在断点处执行
p uintptr(p1) == uintptr(p2)—— 注意必须用uintptr,unsafe.Pointer在 dlv 表达式中不被支持 - 如果其中一个为
nil,p uintptr(p1)会输出0,可直接肉眼比对 - 对切片或 map 的底层指针,得先拆解:比如
s是切片,&s[0]才是底层数组首地址;len(s) > 0必须成立,否则&s[0]panic - 结构体字段地址可用
p &v.field查,但注意字段对齐可能导致地址不连续——别假设&v.a + sizeof(a) == &v.b
调试 CGO 指针时,dlv 显示的地址为什么和 C 里 printf("%p") 不一致?
不是地址错了,是打印格式和上下文不同:dlv 默认以十进制显示 uintptr,而 C 的 %p 是十六进制且带前缀,且可能受 ASLR 影响。
立即学习“go语言免费学习笔记(深入)”;
- dlv 中统一用
p printf("%p", uintptr(ptr))(需开启dlv的 expr 支持,1.22+ 默认开)来对齐 C 输出格式 - CGO 中从 Go 传给 C 的指针,C 侧必须用
C.free或对应释放逻辑,dlv 看不到 C 堆内存布局,无法校验是否已释放 - 若 C 代码里把指针转成了
int再传回 Go,dlv 里用uintptr(intVar)恢复时,要确保该int没被截断(如 32 位 int 存 64 位地址) - 最易忽略的一点:CGO 调用返回后,Go 的 GC 可能回收原对象,而 C 侧仍持有野指针——dlv 断点停在 C 函数内时,Go 变量已不可见,此时只能靠日志或
pprof配合排查










