Сборка мусора и cgo
Можно ли сделать сборщик мусора в дескрипторе Go и освободить память, выделенную через код C? Я прошу прощения, я не использовал C и Cgo раньше, поэтому мои примеры могут нуждаться в пояснении.
Допустим, у вас есть некоторая библиотека C, которую вы хотите использовать, и эта библиотека выделяет некоторую память, которую необходимо освободить вручную. Я хотел бы сделать что-то вроде этого:
package stuff
/*
#include <stuff.h>
*/
import "C"
type Stuff C.Stuff
func NewStuff() *Stuff {
stuff := Stuff(C.NewStuff()) // Allocate memory
// define the release function for the runtime to call
// when this object has no references to it (to release memory)
// In this case it's stuff.Free()
return stuff
}
func (s Stuff) Free() {
C.Free(C.Stuff(s)) // Release memory
}
Есть ли способ для сборщика мусора вызвать Stuff.Free(), когда нет ссылок на *Stuff в среде выполнения Go?
Имею ли я здесь смысл?
Возможно, более прямой вопрос: возможно ли заставить среду выполнения автоматически обрабатывать очистку выделенной памяти на С, написав функцию, которую среда выполнения вызывает при нулевых ссылках на этот объект?
1 ответ
Существует runtime.SetFinalizer
функция, но она не может быть использована на любом объекте, выделенном кодом C.
Однако вы можете создать объект Go для каждого объекта C, который необходимо автоматически освобождать:
type Stuff struct {
cStuff *C.Stuff
}
func NewStuff() *Stuff {
s := &Stuff{C.NewStuff()}
runtime.SetFinalizer(s, (*Stuff).Free)
return s
}
func (s *Stuff) Free() {
C.Free(s.cStuff)
}