Jam*_*dge 5 garbage-collection go cgo
当使用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))
}
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
怎样运行的风险foo->ch由之间的垃圾收集器被释放foo_new和foo_send电话?如果是这样,有没有办法从C端固定Go变量,以防止在我持有对它的引用时释放它?
根据gmp CGo 示例:
垃圾收集是个大问题。对于 Go 世界来说,拥有指向 C 世界的指针并在不再需要时释放这些指针是很好的。为了提供帮助,Go 代码可以定义持有 C 指针的 Go 对象,并对这些 Go 对象使用 runtime.SetFinalizer。
对于 C 世界来说,拥有指向 Go 世界的指针要困难得多,因为 Go 垃圾收集器不知道 C 分配的内存。最重要的考虑因素是不限制未来的实现,因此规则是 Go 代码可以将 Go 指针传递给 C 代码,但必须单独安排 Go 保留对指针的引用,直到 C 完成它。
所以我不确定你是否可以从C端固定变量,但你也许可以通过使用该runtime.SetFinalizer函数从Go端控制变量的垃圾收集。
希望有帮助。