Go保证不变地址吗?

时间:2014-03-05 11:05:39

标签: go garbage-collection specifications

给定一个对象 obj 可以保证

uintptr(unsafe.Pointer(&obj))
无论何时调用,

总是会评估为相同的值?

当然,Go保证如果你把两个指针指向同一个对象,它们总会比较相等。虽然实现可能会移动对象在内存中并透明地更新指向它的所有指针。

如果您考虑像Mark-and-Compact这样的垃圾收集策略,这很有趣。是否允许实现者使用这种垃圾收集策略?

3 个答案:

答案 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运行时我相信它是真的,但依赖它仍然是未定义的行为。但有几点需要注意:

  1. 如果obj为零尺寸类型,则表达式的值可能不唯一,如described in the spec

  2. 在程序的生命周期中,特定的uintptr值可能会引用不同的对象。

答案 2 :(得分:3)

没有绝对保证。特别是如果Go将压缩添加到其标记并清除垃圾收集器。

存储在pointer typeunsafe.Pointer中的地址将在必要时由任何垃圾收集器更新。存储在类型uintptr中的地址作为无符号整数不会被垃圾收集器更新。 uintptr类型不是指针类型,它是整数类型。

  

Numeric types

     

uintptr一个无符号整数,足以存储未解释的   指针值的位

     

converting unsafe.Pointers to uintptr

     

指针应该保持不安全。指针 - 不是uintptrs -   总是

     

拉​​斯

对于您的示例,

uintptr(unsafe.Pointer(&obj))

你有一个无符号整数,而不是一个地址。