【Lua】lua内存泄漏

来源:互联网 发布:java队列处理高并发 编辑:程序博客网 时间:2024/05/20 02:27

我们游戏开始都是用c++写的,后来写了一半的时候加入了lua,现在有4个模块用lua写的逻辑,类对象都是在模拟器里面创建好,基于tolua将对象和相关方法导入到lua中,然后用lua实现逻辑部分。功能实现之后,昨天开始看看lua逻辑部分有没有内存泄漏,网上查了很多资料,边学习边查找。

luaMonitor这个工具还不错,可以看到lua使用的内存变化以及分配内存的变量和函数等,通过这个我看到我们代码确实有泄露。  仔细阅读代码发现了几个局部变量没有写local确实会造成泄露,但是不停的进出一个功能模块,发现内存会持续增加。说明问题就不只是这么简单了。

网上学习了lua的内存垃圾回收机制,大概是这样的:

名为标志和清扫(Mark-and-Sweep)的方式。

基础的Mark-and-Sweep算法是最古老的解决循环引用情况垃圾收集算法之一。
顾名思义,这是一个two phases的算法,可用很简单的文字描述:
(1)Mark phase(标志阶段)
1> 每个可被gc的对象都拥有一个标志位,初始为0(unmarked)。
2> 定义程序中第一层可访问的对象集合为 根对象集合(root set)。
3> 递归遍历根集合中所有对象的引用关系,如果某对象标志位为unmarked,
则标志为1(marked)。
(2)Sweep phase(清扫阶段)
1> 遍历所有现存的对象:将标志位还是unmarked的对象释放;
同时将标志为marked的对象重新标志为unmarked,为下次gc做准备。

 简而言之就是每个对象如果还有引用就不回收,无引用就回收,至于怎么回收,暂时不关心,心有余而力不足啊,以后有时间在学习。对于我上面那个内存持续增加的问题,原因就很明显了,就是不断的有新的东西生成,使用之后呢没有把它的引用计数减掉掉,然后我就在我的代码中加上了这么一段:

for i=1,50 do
collectgarbage("collect")
print(i..'s',collectgarbage("count"))
end

打出log:

[LUA-print] 1s 1831.625

[LUA-print] 2s 1831.625

[LUA-print] 3s 1831.625

[LUA-print] 4s 1831.625

[LUA-print] 5s 1831.625

[LUA-print] 6s 1831.625

[LUA-print] 7s 1831.625

[LUA-print] 8s 1831.625

[LUA-print] 9s 1831.625

[LUA-print] 10s 1831.626953125

[LUA-print] 11s 1831.626953125

[LUA-print] 12s 1831.626953125

[LUA-print] 13s 1831.626953125

[LUA-print] 14s 1831.626953125

[LUA-print] 15s 1831.626953125

[LUA-print] 16s 1831.626953125

[LUA-print] 17s 1831.626953125

[LUA-print] 18s 1831.626953125

[LUA-print] 19s 1831.626953125

[LUA-print] 20s 1831.626953125

[LUA-print] 21s 1831.626953125

[LUA-print] 22s 1831.626953125

[LUA-print] 23s 1831.626953125

[LUA-print] 24s 1831.626953125

[LUA-print] 25s 1831.626953125

[LUA-print] 26s 1831.626953125

[LUA-print] 27s 1831.626953125

[LUA-print] 28s 1831.626953125

[LUA-print] 29s 1831.626953125

[LUA-print] 30s 1831.626953125

[LUA-print] 31s 1831.626953125

[LUA-print] 32s 1831.626953125

[LUA-print] 33s 1831.626953125

[LUA-print] 34s 1831.626953125

[LUA-print] 35s 1831.626953125

[LUA-print] 36s 1831.626953125

[LUA-print] 37s 1831.626953125

[LUA-print] 38s 1831.626953125

[LUA-print] 39s 1831.626953125

[LUA-print] 40s 1831.626953125

[LUA-print] 41s 1831.626953125

[LUA-print] 42s 1831.626953125

[LUA-print] 43s 1831.626953125

[LUA-print] 44s 1831.626953125

[LUA-print] 45s 1831.626953125

[LUA-print] 46s 1831.626953125

[LUA-print] 47s 1831.626953125

[LUA-print] 48s 1831.626953125

[LUA-print] 49s 1831.626953125

发现一个疑惑,当然和我之前问题没什么关系,后面在探究一下:前后面内存不一样多,难道和lua回收内存的机制有关?并不是一次回收干净?偏题了。。。后面在学习。回归我的问题:多次进入该功能模块内存持续泄露。

多次执行上面的内存回收打log的代码,发现每次进入该模块再退出后都会增加大约20个字节的内存。在对比luaMonitor分配内存的对象,觉得频繁分配的function很可疑。分析发现原来是我们的C++的回调函数导入到lua的代码出了问题,没有将回调的function的引用减1。

LUA_FUNCTION handler = (toluafix_ref_function(tolua_S, 3, 0));
self->postRawReq(cmd, [handler](){
CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
CCLuaStack* pStack = pEngine->getLuaStack();
pStack->executeFunctionByHandler(handler, 0);
pStack->removeScriptHandler(handler);
pStack->clean();
});

加上pStack->removeScriptHandler(handler) 这一句测试ok了。




0 0
原创粉丝点击