英文:
Does Go guarantee constant addresses?
问题
给定一个对象_obj_,是否有保证
uintptr(unsafe.Pointer(&obj))
无论何时调用,都会始终评估为相同的值?
当然,Go语言保证如果你获取两个指向同一对象的指针,它们将始终比较相等。然而,实现可能会将对象在内存中移动,并透明地更新所有指向它的指针。
如果考虑到像标记-压缩这样的垃圾回收策略,这就变得有趣了。实现者是否允许使用这样的垃圾回收策略?
英文:
Given an object obj is there a guarantee that
uintptr(unsafe.Pointer(&obj))
will always evaluate to the same value regardless of when it is called?
Of course, Go guarantees that if you take two pointers to the same object, they will always compare equal. It might be possible though that an implementation moves an object in memory and transparently updates all pointers to it.
This is interesting if you consider garbage collection strategies like Mark-and-Compact. Would an implementor be allowed to use such a garbage collection strategy?
答案1
得分: 21
没有这样的保证,正因为如此才有可能实现一个移动的收集器。
实际上,尽管垃圾收集器今天不会移动堆对象,在Go 1.3中,当需要增长时,堆栈可以移动,因此完全有可能打印出两个不同的指针,因为bigFunc增长了堆栈,导致obj和堆栈上的其他所有内容移动。
英文:
There is no such guarantee, exactly so that it is possible to implement a moving collector.
In fact, although the garbage collector does not move heap objects today, in Go 1.3 stacks can move when needing to grow, so it is entirely possible that
var obj int
fmt.Println(uintptr(unsafe.Pointer(&obj)))
bigFunc()
fmt.Println(uintptr(unsafe.Pointer(&obj)))
will print two different pointers, because bigFunc grew the stack, causing obj and everything else on the stack to move.
答案2
得分: 7
规范中没有任何保证这一点,可能是为了允许将来的语言实现使用紧凑垃圾收集器。在这个golang-nuts的讨论串中,其中一位开发者建议,只要将unsafe.Pointer
值固定在内存中,紧凑垃圾收集器就是可能的,但这不能扩展到所有的unitptr
值。
对于当前的Go运行时,我认为这是正确的,但依赖它仍然是未定义的行为。不过,有几个注意事项:
-
如果
obj
是一个零大小的类型,表达式的值可能不是唯一的,如规范中所述。 -
在程序的生命周期内,特定的
uintptr
值可能指向不同的对象。
英文:
There isn't anything in the specification that guarantees this, probably to allow implementations of the language to use compacting garbage collectors in the future. In this golang-nuts thread one of the developers suggests that a compacting GC would be possible provided unsafe.Pointer
values were pinned in memory, but this couldn't extend to all unitptr
values.
For the current Go runtime I believe it is true, but relying on it would still be undefined behaviour. There are a few caveats though:
-
If
obj
is a zero size type, the value of the expression may not be unique, as described in the spec. -
Over the lifetime of a program, a particular
uintptr
value might refer to different objects.
答案3
得分: 3
没有绝对的保证。特别是如果Go语言将压缩功能添加到其标记和清除垃圾收集器中。
存储在指针类型和unsafe.Pointer
类型中的地址,如果需要,将由任何垃圾收集器进行更新。存储在uintptr
类型中的地址作为无符号整数将不会被垃圾收集器更新。uintptr
类型不是指针类型,而是整数类型。
对于你的示例:
uintptr(unsafe.Pointer(&obj))
你得到的是一个无符号整数,而不是一个地址。
英文:
No absolute guarantee. Especially if Go adds compaction to its mark and sweep garbage collector.
Addresses stored in pointer types and type unsafe.Pointer
will be updated, if necessary, by any garbage collector. Addresses stored in type uintptr
as unsigned integers will not be updated by a garbage collector. The uintptr
type is not a pointer type, it's an integer type.
> Numeric types
>
> uintptr
an unsigned integer large enough to store the uninterpreted
> bits of a pointer value
>
> converting unsafe.Pointers to uintptr
>
> Pointers should have been kept in unsafe.Pointers - not uintptrs -
> always.
>
> Russ
For your example,
uintptr(unsafe.Pointer(&obj))
you have an unsigned integer, not an address.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论