Does Go гарантирует постоянные адреса?

Если у объекта obj есть гарантия, что

uintptr(unsafe.Pointer(&obj))

всегда будет оценивать одно значение независимо от того, когда оно вызывается?

Конечно, Go гарантирует, что если вы возьмете два указателя на один и тот же объект, они всегда будут сравнивать равные. Возможно, возможно, что реализация перемещает объект в память и прозрачно обновляет все указатели на него.

Это интересно, если вы рассматриваете стратегии сбора мусора, такие как Mark-and-Compact. Разрешено ли разработчику использовать такую ​​стратегию сбора мусора?

Ответ 1

Нет такой гарантии, именно так, что можно реализовать подвижный коллектор.

Фактически, хотя сборщик мусора не перемещает объекты кучи сегодня, в Go 1.3 стеки могут двигаться, когда им нужно расти, поэтому вполне возможно, что

var obj int
fmt.Println(uintptr(unsafe.Pointer(&obj)))
bigFunc()
fmt.Println(uintptr(unsafe.Pointer(&obj)))

будет печатать два разных указателя, потому что bigFunc увеличил стек, в результате чего obj и все остальное в стеке перемещались.

Ответ 2

В спецификации нет ничего, что гарантировало бы это, возможно, чтобы позволить языкам использовать компактные сборщики мусора в будущем. В этот поток golang-nuts один из разработчиков предполагает, что возможно сжатие GC при условии, что значения unsafe.Pointer были закреплены в памяти, но это могло бы 't распространяется на все значения unitptr.

В текущем времени Go я верю, что это правда, но полагаться на это все равно будет undefined. Есть несколько предостережений:

  • Если obj - тип нулевого размера, значение выражения может быть не уникальным, так как описанный в спецификации.

  • За время жизни программы конкретное значение uintptr может ссылаться на разные объекты.

Ответ 3

Нет абсолютной гарантии. Особенно, если Go добавляет уплотнение к своей отметке и собирает сборщик мусора.

Адреса, хранящиеся в тип указателя, и введите unsafe.Pointer будет обновляться, если необходимо, любым сборщиком мусора. Адреса, сохраненные в типе uintptr, поскольку целые числа без знака не будут обновляться сборщиком мусора. Тип uintptr не является типом указателя, это целочисленный тип.

Числовые типы

uintptr целое число без знака, достаточно большое для хранения неинтерпретированного бит значения указателя

преобразование unsafe.Pointers в uintptr

Указатели должны храниться в небезопасных.Оценки - не uintptrs - всегда.

Расс

В вашем примере

uintptr(unsafe.Pointer(&obj))

у вас есть целое число без знака, а не адрес.