cgo指针值已更改

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

cgo pointer value changed

问题

我使用cgo为C API(bullet物理引擎)创建了绑定,其中一些函数使用数据指针。我的想法是,我可以将一个指针附加到一个对象上,并在物理引擎调用回调时稍后检索它。我的问题是,当我收到值后,它发生了变化,而我并没有这样做。似乎没有源代码明确地更改该值。

CollisionObject:源代码头文件与该类交互的Go代码

这是我发送值的方式,重新转换为*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

非常感谢您的任何指针(哈哈)!

英文:

I made bindings to a C api (bullet physics engine) using cgo, some functions make use of data pointers. The idea is that I can attach a pointer to an object and retrieve it later when the physics engine invokes a callback. My problem is that when i get the value back, it change and I didn't do it. It seems that no source code is explicitelly changing the value.

CollisionObject: source, header,
The go codes that interracts with that class

heres how i send the values, the reconversion to *int and int is fine, the correct numbers are printed:

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)

But when I get it back from a raytest the value changed:

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

the pointer value itself didnt change, i can look up and see that there was a pointer pointing to this location, but the value its pointing at is different.

Now i'm wondering if maybe go didn't clean the value (garbage collected) since it wouldn't be used anymore and replaced this memory location with something else.

example output (with junk values removed):

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

ANY pointer (hehe) is appreciated cgo指针值已更改

答案1

得分: 1

Go的垃圾回收器不知道由C或C++代码持有的指针,所以没有任何东西可以保持num变量的存活。

你可以通过在Go变量中存储指针的第二个副本来解决这个问题。一种方法是使用一个类型为map[*C.some_c_type]*int或类似类型的全局变量,并在其中存储&num。记得用互斥锁保护这个map,以便在并发访问时行为正确。

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

英文:

Go's garbage collector doesn't know about the pointers held by C or C++ code, so there is nothing to keep the num variable alive.

You can work around this by storing a second copy of the pointer in a Go variable. One way is to use a global variable with a type like map[*C.some_c_type]*int or similar, and store &num there too. Remember to protect the map with a mutex so things behave correctly when you have concurrent access.

In order not to leak, you will need to manually delete &num from the map when the underlying C code is no longer holding a reference to it. If the C library provides the ability to set a destroy notify function when storing the user pointer, this will be easy: just export a Go function to C and use it as the notify function. If it doesn't, but the Go binding knows when the the pointer will be finished with (e.g. if the RigidBody variable is always freed via the Go API, you can do the clean up there.

huangapple
  • 本文由 发表于 2014年11月8日 06:14:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/26810985.html
匿名

发表评论

匿名网友

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

确定