4

我正在使用 cocos2d-x 和 Lua 进行开发。最近我使用 Instruments 并发现了一些废弃的内存:cocos2d-x 对自己的自动释放池中的对象执行释放,但我仍然有来自 Lua 的引用。如何确定这些参考是什么时候出现的?我需要释放该内存以避免在空间中留下废弃的内存分配。我唯一想到的是使用一些 Lua 调试器来处理不是nilLua 指针。

如果我只知道哪个 Lua 引用持有指针,我可以手动释放它。

4

2 回答 2

3

你的问题措辞有点奇怪。但据我了解,您的 Lua 脚本引用了在外部代码中分配的对象。只要 Lua 有这些引用,外部代码就不会释放这些资源。你认为应该释放这些资源。

您应该检查的第一件事是您的 Lua 接口代码使用元方法来正确清理引用。也就是说,当 Lua 完成一个对象引用时,附加了一个元方法 ( __gc),它将通知外部代码 Lua 完成了该对象。

对于本文的其余部分,我将假设此代码存在并且正常运行。您应该自己验证这一点。

鉴于这种假设,您所看到的情况有两个原因之一:

  1. 您的 Lua 代码已使用完所有引用,但尚未清理它们。我的意思是 Lua 脚本不再有任何局部变量、全局变量等中的引用。在这种情况下,发生的事情是 Lua 的垃圾收集器根本还没有运行和清理东西。所以你需要用lua_gc(L, LUA_GCCOLLECT, 0);. 如果是这种情况,那么在运行这个函数之后,所有来自 Lua 的引用都应该被清除。

  2. 你的 Lua 代码仍然有对潜伏的外部对象的活动引用。

处理案例#2 很困难。负责是 Lua 代码的责任。它应该在需要引用内容时存储引用,然后忘记这些引用。我的意思是不要将值存储在非局部变量中(并且通过“非局部”,我还意味着避免嵌套函数定义使用的局部变量)。

没有办法找到那些引用仍然存在的地方;毕竟,Lua 值不一定有名字。此外,Lua 并没有真正给你一种方法来遍历lua_State. 即使有,当然也没有办法简单地将这些引用排除在外。毕竟,Lua 代码仍然可以触摸它们。如果你将它们置空,Lua 代码在尝试与这些对象对话时会崩溃。所以即使你可以做你想做的事,也会适得其反。

我会建议处理此问题的三种方法之一:

  1. 在你的脚本中锻炼纪律。确保您知道所有非 Lua 对象的存储位置。确保这些对象在应有的时候被释放。知道你把这些外部对象放在哪里,并确保它们按时释放。通过“发布”,我的意思是简单地用nil.

  2. 在脚本和源代码之间建立一层绝缘层。与其直接给 Lua 指针指向 Cocos2D-X 对象,不如给它指向一个特殊对象的指针,该对象可能包含对 Cocos2D-X 对象的引用。这样,您可以通过告诉此控制对象删除其引用来直接控制这些对象何时被释放。如果 Lua 调用一个空的控件对象,该函数将返回……一些无害的东西(这样你就不会崩溃)。显然,Lua 应该有一个函数来查看它是否是一个有效的控制对象。

  3. 在 Lua 中做任何你想做的事,然后在需要释放资源时销毁整个 Lua 状态。您当前的方法非常精细。Lua 创建了一些资源,然后 Lua 决定它们何时消失。更严格的资源管理方案是让 Lua 脚本加载一些资源和引用资源。但是到了销毁所有这些资源的时候,你只是lua_closelua_State自己。这将释放所有引用,从而释放这些资源。问题解决了。

于 2012-02-01T17:43:59.920 回答
0

我也偶然发现了这个问题。

不幸的是,尽管 Lua 脚本引擎引用了该对象,但 Cocos2d-x 可以破坏 CCObjects。看来绑定并不完美。

您可以通过在静态包中创建例如 CCNode 来测试这一点,然后将不同的 CCNode 添加到场景中,然后将其移除(触发清理),然后等待帧更新。尽管有一个有效的 lua 引用,但原始的 CCNode 对象将消失,并且尝试在 Lua 中对其调用方法会抛出错误,尽管对象 ~= nil。

您可以通过创建 CCMutableArray_CCObject__ 对象并向其添加 CCObjects 来解决此问题。这会增加这些对象的引用计数,如果没有 lua 引用也被 gc'ed,CCMutableArray_CCObject__ 将不会 gc'ed。

于 2013-06-04T20:05:26.700 回答