【问题标题】:cgo pointer value changedcgo 指针值改变
【发布时间】:2014-11-07 22:14:41
【问题描述】:

我使用 cgo 绑定到 C api(子弹物理引擎),一些函数使用数据指针。这个想法是我可以将一个指针附加到一个对象上,然后在物理引擎调用回调时检索它。我的问题是,当我取回价值时,它会改变,而我没有这样做。似乎没有源代码明确更改该值。

碰撞对象:sourceheaderThe go codes that interracts with that class

这是我如何发送值,重新转换为 *int 和 int 很好,打印正确的数字:

num := x*amounty*amountz + y*amountz + z + 1
ptr := unsafe.Pointer(&num)
fmt.Printf("created %v %v\n", ptr, *(*int)(ptr))
rb := sphere.RigidBody(ptr, 1)

但是当我从 raytest 中返回时,值发生了变化:

ptr := hit.GetUserPointer()
log.Printf("we got back: %v %v", ptr, *(*int)(ptr))

指针值本身没有变化,我可以查看一下,有一个指针指向这个位置,但是它指向的值不同。

现在我想知道是否可能 go 没有清理值(垃圾收集),因为它不再被使用并用其他东西替换了这个内存位置。

示例输出(已删除垃圾值):

created: 0xc2080006e0 40
2014/11/07 17:10:01  we got back: 0xc2080006e0 4921947622888946315

感谢任何指针(呵呵):)

【问题讨论】:

  • 它正在被 GC 处理。您需要在 Go 中保持该指针处于活动状态,这样它就不会。
  • @JimB 同样,Go 的 GC 允许移动指针。在 C 端存储指针绝对不安全。
  • @Jsor,从技术上讲是正确的,但还没有。有很多代码将指针传递给 cgo,因为它是我们目前拥有的最好的。这应该是go1.5更好的定义。 (在这种情况下,虽然没有很好的理由使用指针,但将值复制进去)

标签: pointers go bullet cgo


【解决方案1】:

Go 的垃圾收集器不知道 C 或 C++ 代码持有的指针,因此没有什么可以让 num 变量保持活动状态。

您可以通过将指针的第二个副本存储在 Go 变量中来解决此问题。一种方法是使用具有map[*C.some_c_type]*int 或类似类型的全局变量,并将&num 也存储在那里。请记住使用互斥锁保护映射,以便在您具有并发访问权限时正常运行。

为了不泄漏,当底层 C 代码不再持有对 &num 的引用时,您需要从映射中手动删除它。如果 C 库提供了在存储用户指针时设置销毁通知函数的能力,这将很容易:只需将 Go 函数导出到 C 并将其用作通知函数。如果没有,但 Go 绑定知道指针何时结束(例如,如果 RigidBody 变量总是通过 Go API 释放,您可以在那里进行清理。

【讨论】:

    猜你喜欢
    • 2014-03-01
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 2018-12-31
    • 2017-08-01
    • 1970-01-01
    相关资源
    最近更新 更多