由于垃圾收集,指针会改变 Go 中的值吗?

Do pointers change value in Go due to garbage collection?

我是一个相对新手。我一直在使用 cgo 并构建到 C api 的接口。 C api 使用已注册的回调和回调的 void* cookie 参数。

下面是一些代码来说明我的问题:

/*
void cb(void *cookie) {
   callGo(cookie);
}

go_register_cb(void *ptr) {
   register_cb(&cb, ptr);
}
*/
import "C"

import "C"

//export callGo
callGo(ptr unsafe.Pointer) {
    x := (*MyStruct)(ptr)
    x.doSomething()
}

func (x *MyStruct) Start() {
    C.go_register_cb(unsafe.Pointer(x))
}

此代码导致有关 Go 指针指向 Go 指针的运行时错误。

我想我理解将 Go 指针保留在 C-land 中的基本含义,即在 Go 垃圾收集器中不会考虑 C-land 引用,因此 C 可能最终使用陈旧的引用。

我不能将 Go 指针传递给本身包含 Go 指针的数据结构的具体要求更令人费解。唯一对我有意义的是 Go 中的指针可能会由于垃圾回收而改变值(即它们指向的地址)。是这样吗?

在运行时动态检查这些在 Go 代码和 C 代码之间传递指针的规则。所以当你打破它们时,就会发生错误。

你猜对了。由于垃圾收集(指针已更新),允许更改地址。

备注here from golang.org:

Even if a uintptr holds the address of some object, the garbage collector will not update that uintptr's value if the object moves, nor will that uintptr keep the object from being reclaimed.

因此由于 gc 移动对象是可能的。