Golang中如何解决runtime error: cgo参数包含Go指针指向Go指针的问题
Golang中如何解决runtime error: cgo参数包含Go指针指向Go指针的问题 我想将一个 Go 指针通过 C 传递回 Go 回调函数……并收到上述错误。如果我通过以下方式禁用 cgo 检查器:
export GODEBUG=cgocheck=0
一切运行正常;
详情:我想将 argv 变量 []interface{} 通过 C 传递回 Go
// 问题:[ErrorCatch] runtime error: cgo argument has Go pointer to Go pointer
// 解决:export GODEBUG=cgocheck=0
func (this *MqC) Send (callSig string, argv ...interface{}) {
hdl := this.getCTX()
callSig_ptr := (C.MQ_CST)(C.CString(callSig))
defer C.free((unsafe.Pointer)(callSig_ptr))
var errVal C.enum_MqErrorE = C.gomsgque_Send(hdl, callSig_ptr, C.MQ_INT(len(argv)), unsafe.Pointer(&argv))
if (errVal > C.MQ_CONTINUE) { MqErrorC_Check(C.MQ_MNG(hdl), errVal) }
}
回调函数是
//export atomSet
func atomSet( hdl C.MQ_MNG, objv unsafe.Pointer, skip C.MQ_INT, typ C.enum_MqSendE,
inP unsafe.Pointer) C.enum_MqErrorE {
ifc := (*(*[]interface{})(objv))[skip]
...
}
现在我希望能有一个对 Go 更友好的解决方案。 谢谢。
更多关于Golang中如何解决runtime error: cgo参数包含Go指针指向Go指针的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我不了解Go的内部工作原理,但这里有一个猜测:
根据对callSig_ptr字符串指针的延迟释放,在我看来callSig和argv都不应该在调用(*MqC).Send之后继续存在,但Go编译器并不知道这一点。它只是看到你将一个局部参数(argv)的地址传递给了C,并且这个值可能需要在调用gomsgque_Send之后继续存活。
如果gomsgque_Send在“C世界”的某个地方存储了对&argv的引用,然后(*MqC).Send返回,接着发生了一次垃圾回收(清理了在调用(*MqC).Send时逃逸到堆上的argv),那么当最终调用atomSet时,它会因为argv已被清理而因段错误而崩溃。
如果callSig和argv的生命周期不需要在gomsgque_Send返回后继续存在,可以尝试在调用gomsgque_Send之外获取地址,像这样:
func (this *MqC) Send (callSig string, argv ...interface{}) {
hdl := this.getCTX()
callSig_ptr := (C.MQ_CST)(C.CString(callSig))
defer C.free((unsafe.Pointer)(callSig_ptr))
argv_ptr := unsafe.Pointer(&argv)
var errVal C.enum_MqErrorE = C.gomsgque_Send(hdl, callSig_ptr, C.MQ_INT(len(argv)), argv_ptr)
if (errVal > C.MQ_CONTINUE) { MqErrorC_Check(C.MQ_MNG(hdl), errVal) }
}
我不确定这一定能行,但可以试试看。
更多关于Golang中如何解决runtime error: cgo参数包含Go指针指向Go指针的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


