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

uintptr(unsafe.Pointer(&obj))

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

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

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

15
fuz 5 Мар 2014 в 15:05

3 ответа

Лучший ответ

Нет такой гарантии, как раз для того, чтобы можно было реализовать движущийся коллектор.

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

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

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

21
Russ Cox 5 Мар 2014 в 21:28

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

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

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

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

7
James Henstridge 5 Мар 2014 в 13:37

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

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

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

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

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

Указатели следовало хранить в unsafe. Указатели - не uintptrs - всегда.

Russ

Для вашего примера,

uintptr(unsafe.Pointer(&obj))

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

3
peterSO 5 Мар 2014 в 15:02