给定一个对象 obj 可以保证
uintptr(unsafe.Pointer(&obj))
无论何时调用,总是会评估为相同的值?
当然,Go保证如果你把两个指针指向同一个对象,它们总会比较相等。虽然实现可能会移动对象在内存中并透明地更新指向它的所有指针。
如果您考虑像Mark-and-Compact这样的垃圾收集策略,这很有趣。是否允许实现者使用这种垃圾收集策略?
答案 0 :(得分:19)
没有这样的保证,确实可以实现移动的收集器。
实际上,虽然垃圾收集器今天不会移动堆对象,但是在Go 1.3中,堆栈可以在需要增长时移动,所以完全有可能
var obj int
fmt.Println(uintptr(unsafe.Pointer(&obj)))
bigFunc()
fmt.Println(uintptr(unsafe.Pointer(&obj)))
将打印两个不同的指针,因为bigFunc增加了堆栈,导致obj和堆栈中的其他所有内容移动。
答案 1 :(得分:8)
规范中没有任何内容可以保证这一点,可能是为了允许该语言的实现在将来使用压缩垃圾收集器。在this golang-nuts thread中,其中一位开发人员建议,如果unsafe.Pointer
值固定在内存中,则可以使用压缩GC,但这不能扩展到所有unitptr
值。
对于当前的Go运行时我相信它是真的,但依赖它仍然是未定义的行为。但有几点需要注意:
如果obj
为零尺寸类型,则表达式的值可能不唯一,如described in the spec。
在程序的生命周期中,特定的uintptr
值可能会引用不同的对象。
答案 2 :(得分:3)
没有绝对保证。特别是如果Go将压缩添加到其标记并清除垃圾收集器。
存储在pointer type和unsafe.Pointer
中的地址将在必要时由任何垃圾收集器更新。存储在类型uintptr
中的地址作为无符号整数不会被垃圾收集器更新。 uintptr
类型不是指针类型,它是整数类型。
uintptr
一个无符号整数,足以存储未解释的 指针值的位converting unsafe.Pointers to uintptr
指针应该保持不安全。指针 - 不是uintptrs - 总是
拉斯
对于您的示例,
uintptr(unsafe.Pointer(&obj))
你有一个无符号整数,而不是一个地址。