当通过基于 C.malloc
的调用分配单个对象时,我们必须释放新项目,因为 Go 垃圾收集器不知道它们。
如:
s := C.CString(l)
defer C.free(unsafe.Pointer(s))
但是,当我们创建 C 对象的 slice 时,我们需要释放它们吗?
如:
b := make([]C.uchar, C.int(40))
我试图使用类似 defer C.free(unsafe.Pointer(&b[0]))
的东西,但是它会产生 free(): invalid pointer
和一个中止信号。
我看到三个可能的答案:
- Go 垃圾收集器知道通过
make
调用创建的对象,因此b
将被 Go 运行时垃圾收集。 - Go 垃圾收集器知道通过
make
调用创建的 slice ,但不知道 slice 中包含的C.uchar
。因此我们需要遍历 slice ,并释放每个项目 - 我错误地调用了 slice
b
的释放。
如果有的话,我的结论中哪些是正确的?否则实际发生了什么?
最佳答案
没那么复杂
cgo
生成一个 Go 类型 C.uchar
,其内存布局完全匹配 C
类型 unsigned char
。
Go 表达式 make([]C.uchar, 40)
像往常一样分配一个 Go slice ,其底层数组为 Go 类型 C.uchar
。
Go 有一个垃圾收集器 (GC)。当不再有任何 Go 对 slice 及其底层数组的引用时,它就有资格进行 Go 垃圾回收。
Go GC 不知道也不关心任何 C 代码。
参见 Go: Command cgo .
关于go - 释放 C 对象的 Go 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54972955/