在C++中使用Luabind创建循环中的对象导致应用程序崩溃。

我正在尝试与我的游戏引擎原型一起使用Lua,但遇到了奇怪的错误。

我的目标是使用Lua在循环中创建X个对象并渲染它们。

如果我这样做,代码没有错误,但游戏会在随机时间从立即崩溃到几秒钟。如果我只使用循环中创建的对象而不是手动创建的对象,那么游戏会立即崩溃。

但是,如果我在C ++中编写等效的Lua代码,则可以毫无问题地运行。

这是我Lua绑定

每个方法均接受并返回void,除了AddChild

Sprite、Box和Circle Objects都继承自Node类。

有人有什么想法可能会导致这种奇怪的错误吗?我很高兴得到任何帮助。

点赞
用户734069
用户734069

你有严重的所有权问题。

在C/C++中,如果一段代码或对象承担销毁指针或其他资源的责任,则该代码/对象“拥有”该指针或资源。它在需要的时候保持其存活,并确保在使用完它后销毁它。

对于任何稍微复杂的C或C++程序,保持对谁拥有什么的理解都是至关重要的。

当Luabind从Lua创建一个C++对象时,Lua脚本“拥有”该对象。这意味着Lua的垃圾回收器将决定何时删除它。

因此,以下代码将创建一个Sprite对象,其生命周期由Lua状态管理。当Lua状态不再具有任何活动引用时,Lua状态将可以删除它。

local s = Sprite("circle.png", x, y, 0)

我不知道你的代码是怎么工作的,但这一行:

local o = CircleObject(s)

表明CircleObject的构造函数应该声明对其所接收的对象的所有权(因此CircleObject决定何时删除它)。如果是这样的话,你需要在将该构造函数与Luabind绑定时实际说明。

如果CircleObject的构造函数不应该拥有所有权,那么......坦白地说,你的设计值得怀疑;长期存储你不拥有的指针只会引发问题。但是,如果它真的应该存储由其他人拥有的指针,那么你需要使用Lua机制来确保在CircleObject存在时,Sprite仍然存活。

同样,Node::AddChild函数似乎在声明它所接收的任何节点的所有权。这应该是这样做的:

.def("AddChild", &Node::AddChild, adopt(_1))

这里的“_1”表示该函数的第一个参数。这意味着Node声称拥有第一个参数的所有权;如果它被Lua拥有,那么所有权链就被打破了,C++现在拥有该对象。

就我个人而言,我认为这个API对于Lua来说......不太好。你似乎希望所有较小的对象所有权都在C++代码中完成。因此,Lua应该调用C++函数来设置所有这些较小的对象,而无需干扰Lua。Lua应该调用NodeManager的成员函数来获取/创建一个Node,然后它应该调用一个函数来在该Node中创建一个Sprite。

Lua不应该处理BoxObject之类的细节。它不应该直接创建一个Sprite对象并将其放入Node中。

此外,就我个人而言,这个API对于C++也不好。如果需要将Sprite存储在某种容器中,并且需要将该容器存储在某种Node中,则不应该在不存储它在容器中的情况下创建Sprite。这就是工厂函数的作用。我甚至不确定BoxObject和CircleObject是用来做什么的,因为Sprite似乎在做所有的工作。

2012-08-04 22:14:33