英文:
golang cgo: libevent handler values are set to null during execution
问题
我正在翻译以下内容:
我正在将这个C API(https://github.com/shammash/vde3)移植到Go语言,该库有自己的事件循环,使用libevent,我正在使用CGO。
该库需要一个完整的vde_event_handler,其结构如下:
{event_add = 0x7fffe4de0db0, event_del = 0xc2000123a8, timeout_add = 0xc200000090, timeout_del = 0xc200010400}
一个由函数指针组成的结构体。
在执行过程中,这些字段被设置为NULL,我无法理解为什么会这样,我认为可能是Go的垃圾回收器(由于某种原因)发现了悬空引用并将其删除,但这不应该是问题所在。
这是有问题的函数:https://github.com/kurojishi/govde3/blob/master/govde.go#L23
func createNewEventHandler() *C.vde_event_handler {
var libevent_eh C.vde_event_handler
C.event_base_new()
return &libevent_eh
}
以下是gdb日志:
(gdb) p *libevenet_eh
当前上下文中没有符号“libevenet_eh”。
(gdb) p *libevent_eh
$1 = {event_add = 0x7fffe0000900, event_del = 0x30302e3028, timeout_add = 0x65736c6166, timeout_del = 0x0}
(gdb) info locals
libevent_eh = 0xc200000098
err = {__methods = 0x0, __object = 0x0}
(gdb) n
Breakpoint 1, govde.createNewEventHandler ()
at /home/kurojishi/golang/src/github.com/kurojishi/govde3/govde.go:23
23 func createNewEventHandler() C.vde_event_handler {
(gdb) info locals
$ret11 = {event_add = 0x7fffe4de0db0, event_del = 0xc2000123a8, timeout_add = 0xc200000090, timeout_del = 0xc200010400}
(gdb) n
Breakpoint 2, govde.createNewEventHandler ()
at /home/kurojishi/golang/src/github.com/kurojishi/govde3/govde.go:24
24 var libevent_eh C.vde_event_handler
(gdb) info locals
libevent_eh = {event_add = 0x0, event_del = 0x3, timeout_add = 0x7fffe4de0f8f, timeout_del = 0x7fffe4de0f8f}
$ret11 = {event_add = 0x0, event_del = 0x0, timeout_add = 0x0, timeout_del = 0x0}
英文:
i'm working on porting this C API in go https://github.com/shammash/vde3, the library has is own event loop that use libevent, i'm using CGO.
the library require a full vde_event_handler that is composed this way
{event_add = 0x7fffe4de0db0, event_del = 0xc2000123a8, timeout_add = 0xc200000090, timeout_del = 0xc200010400}
a struct with a series of pointers to functions
during execution this field are set to NULL and i can't understand why, i think it may be the go garbage collector that (for some reason) find the reference dandling and remove them, but this shouldn't be the case
this is the incriminated function https://github.com/kurojishi/govde3/blob/master/govde.go#L23
func createNewEventHandler() *C.vde_event_handler {
var libevent_eh C.vde_event_handler
C.event_base_new()
return &libevent_eh
}
and here is a gdb log
(gdb) p *libevenet_eh
No symbol "libevenet_eh" in current context.
(gdb) p *libevent_eh
$1 = {event_add = 0x7fffe0000900, event_del = 0x30302e3028, timeout_add = 0x65736c6166, timeout_del = 0x0}
(gdb) info locals
libevent_eh = 0xc200000098
err = {__methods = 0x0, __object = 0x0}
(gdb) n
Breakpoint 1, govde.createNewEventHandler ()
at /home/kurojishi/golang/src/github.com/kurojishi/govde3/govde.go:23
23 func createNewEventHandler() C.vde_event_handler {
(gdb) info locals
$ret11 = {event_add = 0x7fffe4de0db0, event_del = 0xc2000123a8, timeout_add = 0xc200000090, timeout_del = 0xc200010400}
(gdb) n
Breakpoint 2, govde.createNewEventHandler ()
at /home/kurojishi/golang/src/github.com/kurojishi/govde3/govde.go:24
24 var libevent_eh C.vde_event_handler
(gdb) info locals
libevent_eh = {event_add = 0x0, event_del = 0x3, timeout_add = 0x7fffe4de0f8f, timeout_del = 0x7fffe4de0f8f}
$ret11 = {event_add = 0x0, event_del = 0x0, timeout_add = 0x0, timeout_del = 0x0}
答案1
得分: 3
你在createNewEventHandler函数中为Go分配了一个新的事件处理程序,并将其传递给VdeContext.Init函数中的C代码,然后丢弃了指针。这样做的效果是,在VdeContext.Init函数返回后的某个时间点,Go垃圾回收器将回收事件处理程序的结构,即使C代码仍然持有指向它的指针。代码将持有指向内存的指针,而该内存将不可预测地发生变化。
当你在Go中分配内存并将指针传递给C时,你必须在C代码需要引用它的时间内保持指针在Go中的存活状态。
英文:
You are allocating a new event handler in Go in createNewEventHandler, passing it to the C code in VdeContext.Init, and then dropping the pointer. The effect is that sometime after VdeContext.Init returns, the Go garbage collector will collect the event handler structure, even though the C code still has a pointer to it. The code will be left holding a pointer to memory that will change unpredictably.
When you allocate memory in Go and pass a pointer to C, you must keep the pointer alive in Go for as long as the C code needs to reference it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论