5

CGo を使用して C コードと Go をインターフェイスする場合、C 側で Go 変数への参照を保持している場合、そのオブジェクトがガベージ コレクターによって解放されるリスクがありますか?それとも GC は、によって管理される変数内のポインターを認識しますか? C面?

私が求めていることを説明するために、次のサンプル プログラムを検討してください。

行くコード:

package main

/*
typedef struct _Foo Foo;
Foo *foo_new(void);
void foo_send(Foo *foo, int x);
int foo_recv(Foo *foo);
*/
import "C"

//export makeChannel
func makeChannel() chan int {
    return make(chan int, 1)
}

//export sendInt
func sendInt(ch chan int, x int) {
    ch <- x
}

//export recvInt
func recvInt(ch chan int) int {
    return <-ch
}

func main() {
    foo := C.foo_new()
    C.foo_send(foo, 42)
    println(C.foo_recv(foo))
}

C コード:

#include <stdlib.h>
#include "_cgo_export.h"

struct _Foo {
    GoChan ch;
};

Foo *foo_new(void) {
    Foo *foo = malloc(sizeof(Foo));
    foo->ch = makeChannel();
    return foo;
}

void foo_send(Foo *foo, int x) {
    sendInt(foo->ch, x);
}

int foo_recv(Foo *foo) {
    return recvInt(foo->ch);
}

との呼び出しfoo->chの間にガベージ コレクターによって解放されるリスクがありますか? もしそうなら、C側からGo変数を固定して、参照を保持している間に解放されないようにする方法はありますか?foo_newfoo_send

4

1 に答える 1

3

gmp CGoの例によると:

ガベージ コレクションは大きな問題です。Go の世界が C の世界へのポインターを持ち、それらのポインターが不要になったときにそれらのポインターを解放することは問題ありません。これを支援するために、Go コードは C ポインターを保持する Go オブジェクトを定義し、それらの Go オブジェクトで runtime.SetFinalizer を使用できます。

Go ガベージ コレクターは C によって割り当てられたメモリを認識しないため、C の世界が Go の世界へのポインターを持つことははるかに困難です。最も重要な考慮事項は、将来の実装を制約しないことです。 Go ポインターを C コードに渡しますが、C が処理を完了するまで、Go がポインターへの参照を保持できるように別途調整する必要があります。

なので、C側から変数を固定できるかどうかはわかりませんが、関数を使えばGo側から変数のガベージコレクションを制御できるかもしれませんruntime.SetFinalizer

それが役立つことを願っています。

于 2013-12-04T01:04:12.433 に答える