Сборка мусора и 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)
}
Другие вопросы по тегам