给定一个对象obj,是否有保证?
uintptr(unsafe.Pointer(&obj))
即使在任何时候调用,它都将始终评估为相同的值吗?
当然,Go保证如果您获取指向同一对象的两个指针,它们将始终相等。不过,实现可能会将对象移动到内存中并透明地更新对它的所有指针。
如果您考虑像标记压缩算法这样的垃圾收集策略,则此事很有趣。实现者是否允许使用这种垃圾收集策略?
给定一个对象obj,是否有保证?
uintptr(unsafe.Pointer(&obj))
即使在任何时候调用,它都将始终评估为相同的值吗?
当然,Go保证如果您获取指向同一对象的两个指针,它们将始终相等。不过,实现可能会将对象移动到内存中并透明地更新对它的所有指针。
如果您考虑像标记压缩算法这样的垃圾收集策略,则此事很有趣。实现者是否允许使用这种垃圾收集策略?
没有这样的保证,正是因为这样才能实现移动收集器。
事实上,虽然垃圾收集器今天不会移动堆对象,在Go 1.3中,当需要增长时,栈可以移动,因此完全有可能
var obj int
fmt.Println(uintptr(unsafe.Pointer(&obj)))
bigFunc()
fmt.Println(uintptr(unsafe.Pointer(&obj)))
会打印出两个不同的指针,因为bigFunc扩大了栈,导致obj和栈上的其他所有内容移动。
unsafe.Pointer
值固定在内存中,就可以实现压缩式 GC,但这不能扩展到所有 unitptr
值。如果 obj
是零大小类型,则表达式的值可能不唯一,正如规范中所述。
在程序的生命周期内,特定的 uintptr
值可能指向不同的对象。
unsafe.Pointer
中的地址将由任何垃圾回收器在必要时进行更新。 存储在类型uintptr
中的地址作为无符号整数将不会被垃圾回收器更新。 uintptr
类型不是指针类型,而是整数类型。
uintptr
一个无符号整数,足够大,可以存储指针值的未解释位指针应始终保留在unsafe.Pointers中-而不是uintptrs中。
Russ
对于你的示例,
uintptr(unsafe.Pointer(&obj))
你有一个无符号整数,而不是一个地址。
unintptr
并期望 GC 保持相关分配的存活。在精确 GC 中,只考虑实际指针变量,这种情况不会发生。 - James Henstridge