3 回答
TA贡献2037条经验 获得超6个赞
问题在于,当 C 代码存储 Go 指针(在这种情况下,指向回调函数的指针)时,垃圾收集器无法在 C 代码中跟踪该指针,并且可能会垃圾收集该指针指向的内存,如果没有Go 代码正在引用它。这将导致 C 代码在尝试访问该内存时崩溃。运行时只知道 C 代码保留了指针(这就是它会恐慌的原因),但它不知道 C 代码稍后将用它做什么以及将保留它多长时间。
为了避免这种情况,大多数库使用的技巧是在 Go 中也保持一个指针(例如在全局映射中),以确保内存免受垃圾收集器的影响。go-qml 也使用了这个技巧。这个技巧有效,但编译器和垃圾收集器不知道它确实有效,他们无法验证您没有犯错(例如删除 Go 指针,而 C 代码仍然有它的指针)。
在 Go 1.6 中,Go 开发人员决定对此非常严格,他们根本不再允许 C 代码保留 Go 指针。但是,如果您禁用此检查,则在这种情况下一切仍然有效,因为 go-qml 正确实现了该技巧(但是,将来可能会中断,例如,如果 go 实现了移动垃圾收集器)。
这是关于它的问题:https : //github.com/go-qml/qml/issues/170
旁注:在这种特定情况下,传递给 C 的是一个指向 an 的指针interface{}
,它本身包含一个指向该函数的指针。这就是为什么您会收到错误“cgo 参数具有指向 Go 指针的 Go 指针”的原因。不允许这样做的原因是在 C 调用期间更难以保护这些指针免受 GC 的影响,而且不值得,因此被禁止(https://github.com/golang/go/问题/12416#issuecomment-136473697)。然而,即使这被允许,代码仍然会违反关于 C 代码保留 Go 指针副本的规则。这在 Go 1.6 中实际上不是问题,因为它没有实现移动垃圾收集器,但是制定了规则以便以后可以实现。
TA贡献1828条经验 获得超4个赞
如果你只是在玩,我建议尝试使用 go 1.5.3。Go 1.6 在使用 cgo 时引入了一组不同的内存指针约束,这是一个更具限制性的集合,并且有可能一些专为旧版本 go 设计的 go 包现在打破了一两个 go 规则。
如果是这种情况,让旧包与 go 1.6 一起工作,其中 C 被允许调用 go 闭包,可能更难修复。但我还没有这方面的第一手经验。
TA贡献1829条经验 获得超4个赞
感谢这里的所有帮助。我写了一篇关于在 Go 中使用 QML 的初学者教程。可以在这里查看。如果我遇到更多错误并找到修复程序,我会不断更新它。感谢大家的帮助。QML/GO 是一个很棒的组合。
https://golog.co/blog/article/Using_Go_with_QML_part_1
- 3 回答
- 0 关注
- 351 浏览
添加回答
举报