Итак, я узнал, как создать фрагмент из небезопасного указателя в Go:
func cArray2ByteSlice(array unsafe.Pointer, len int) (list []byte) {
sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&list)))
sliceHeader.Cap = len
sliceHeader.Len = len
sliceHeader.Data = uintptr(array)
return list
}
У меня есть окно возможности получить доступ к памяти кучи на array unsafe.Pointer
между вызовом внешнего C API lock
и unlock
.
В конечном итоге ГХ попытается собрать срез list []byte
.
Дело в том, что заголовок слайса находится в куче, выделенной golang, а sliceHeader.Data
- нет.
Достаточно ли умен GC, чтобы игнорировать выделение кучи без голангов в этой ситуации, как и в большинстве других?
После вызова unlock
я хочу быть уверен, что Go GC не пытается освободить память кучи на sliceHeader.Data
.
Кроме того, если я хочу скопировать данные для использования за пределами периода lock
/ unlock
, я предполагаю, что мог бы вместо этого вернуть эту переменную:
var safeList []byte = list[:]
Я никогда не слишком много играл с GC, особенно в том, что касается cgo, но обратите внимание, что заголовок среза и базовый массив - это два совершенно разных распределения памяти. Заголовки срезов могут и часто собираются с помощью GC без GC, потому что на этот массив по-прежнему ссылаются где-то еще. Так что нет причин ожидать, что базовые данные обязательно будут GC только потому, что это заголовок среза. Также стоит отметить, что заголовок слайса в этом случае почти наверняка размещен в стеке, поскольку он возвращается как копия (то есть не как
*[]byte
).