golang cgo: 在执行过程中,libevent处理程序的值被设置为null。

huangapple go评论87阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2014年4月10日 20:32:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/22988184.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定