CGO开发疑问:C.free()使用时机及C.CString内存分配规则
CGO内存管理疑问解答
待分析的CGO代码
func Encode(p SomeStruct) (buf []byte, err error) { var bs bytes.Buffer if err = json.NewEncoder(&bs).Encode(p); err != nil { return } in := C.CString(bs.String()) defer C.free(unsafe.Pointer(in)) //Is this necessary? res := make([]byte, 1024) out := C.CString(string(res)) defer C.free(unsafe.Pointer(out)) //and this one res := C.encode(in, out, 1024) //int encode(char *, void *, int) //... ... }
技术问询
- 是否需要调用
C.free()来避免内存泄漏?我认为无需调用,因为变量由Go而非C分配,该观点是否正确? C.CString是否会始终分配内存,还是仅在必要时才进行内存分配?
C.CString官方说明(中文翻译)
// Go字符串转C字符串
// C字符串通过malloc在C堆上分配内存。
// 调用者有责任安排内存释放,比如调用C.free(如果需要C.free请确保包含stdlib.h头文件)。
func C.CString(string) *C.char
问题解答
1. 是否需要调用C.free()?
你的观点错误,必须调用C.free()来避免内存泄漏。
根据官方说明,C.CString是在C堆上用malloc分配的内存,Go的垃圾回收器无法管理C堆的内存。不管初始数据来自Go还是其他地方,只要是C.CString创建的指针,就必须由调用者手动调用C.free释放,否则会造成C堆的内存泄漏。
另外代码里的out变量:你用make([]byte,1024)创建Go切片后转成字符串再调用C.CString,这时候依然会在C堆分配新内存,同样需要手动释放。
2. C.CString是否始终分配内存?
是的,C.CString始终会在C堆上分配新内存。它会把Go字符串的内容复制到C堆分配的内存块中,并添加C字符串要求的末尾\0终止符,不会复用已有内存,每次调用都会执行新的内存分配操作。
内容的提问来源于stack exchange,提问作者xrfang
相关产品推荐
相关产品推荐

