如何通过Lua跟踪内存泄漏/放弃?

时间:2012-02-01 16:51:42

标签: iphone lua memory-management cocos2d-x

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

如果我只知道哪个Lua引用包含指针,那么我可以手动释放它。

2 个答案:

答案 0 :(得分:2)

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

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

对于本文的其余部分,我将假设此代码存在且功能正常。你应该自己验证一下。

鉴于这种假设,您所看到的内容有两个原因:

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

  2. 您的Lua代码仍然存在对潜伏的外部对象的有效引用。

  3. 处理案例#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_close lua_State本身。这将释放所有引用,从而释放这些资源。问题解决了。

答案 1 :(得分:0)

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

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

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

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