gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 12:06:37 26 4
gpt4 key购买 nike

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

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

sprite = Sprite("icon.jpg", 300, 300, 0)
sprite2 = Sprite("icon.jpg", 100, 100, 0)

b1 = BoxObject(sprite)
b2 = BoxObject(sprite2)

sprite3 = Sprite("circle.png", 200, 100, 0)
sprite4 = Sprite("circle.png", 300, 100, 0)

b3 = CircleObject(sprite3)
b4 = CircleObject(sprite4)

n = Node()
n:AddChild(b1)
n:AddChild(b2)
n:AddChild(b3)
n:AddChild(b4)

for i = 0, 10, 1 do
x = math.random(700)
y = math.random(500)
n:AddChild(BoxObject(Sprite("icon.jpg", x, y, 0)))
end

for i = 0, 10, 1 do
x = math.random(700)
y = math.random(500)
local s = Sprite("circle.png", x, y, 0)
local o = CircleObject(s)
n:AddChild(BoxObject)
end

如果我这样做,代码可以正常运行,但游戏会随机崩溃,从瞬间到几秒不等。如果我将此代码仅用于在循环中创建的对象,而不是手动创建的对象,游戏会立即崩溃。

但是,如果我用 C++ 编写等效的 Lua 代码,它运行起来没有任何问题。

for(int i = 0; i < 20; i++){
float x = rand() % 700;
float y = rand() % 500;

n->AddChild(new BoxObject(new Sprite("icon.jpg", x, y)));
}

for(int i = 0; i < 20; i++){
float x = rand() % 700;
float y = rand() % 500;

n->AddChild(new CircleObject(new Sprite("circle.png", x, y)));
}

这是我的 Lua 绑定(bind)

static void Lua(lua_State *lua){
luabind::module(lua)
[
luabind::class_<Node>("Node")
.def(luabind::constructor<>())
.def(luabind::constructor<float, float, float>())
.def("Render", &Node::Render)
.def("Move", &Node::Move)
.def("Rotate", &Node::Rotate)
.def("AddChild", &Node::AddChild)
.def("RotateAroundPoint", &Node::RotateAroundPoint)
];
}

除 AddChild 外,每个方法都接受并返回 void

virtual void AddChild(Node *child);

Sprite 和 Box a and Circle 对象是从 Node 类继承的。

有没有人知道是什么导致了这个奇怪的错误?我很乐意提供任何帮助。

最佳答案

您有严重的所有权问题。

在 C/C++ 中,一段代码“拥有”一个指针或其他资源,前提是该代码或对象负责销毁它。它在需要时保持事件状态,并确保在使用完它时将其销毁。

了解谁拥有对任何稍微复杂的 C 或 C++ 程序来说至关重要的东西。

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

所以这样:

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

将创建一个 Sprite 对象,其生命周期由 Lua 状态控制。当 Lua 状态不再对它有任何事件引用时,Lua 状态将可以自由删除它。

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

local o = CircleObject(s)

建议 CircleObject 的构造函数应该声明对给定对象的所有权(因此 CircleObject 决定何时删除它)。如果这是真的,那么当您将此构造函数与 Luabind 绑定(bind)时,您需要实际说明这一点。

如果 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,然后它应该调用一个函数来创建一个 Sprite在那个 Node 中。

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

此外,就我个人而言,此 API 也不适合 C++。如果 Sprite 需要存储在某种容器中,并且该容器需要存储在某种Node 中,那么就不可能创建一个 Sprite 没有将其存储在容器中。这就是工厂函数的用途。我什至不确定 BoxObjectCircleObject 是干什么用的,因为 Sprite 似乎在做所有的工作。

关于c++ - 使用 C++ 中的 Luabind 在循环中创建的对象导致应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11809619/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com