Сборка мусора и cgo - PullRequest
       27

Сборка мусора и cgo

11 голосов
/ 02 марта 2012

Можно ли сделать сборщик мусора в дескрипторе 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 Ответ

14 голосов
/ 02 марта 2012

Существует функция 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)
}
...