lua内存泄露检测原理
上次写了一个lua内存泄露检测的脚本,现在将它的实现原理拿出来和大家分享一下,希望能有所帮助。 lua内存泄露: ? ? ? ? 首先第一点,lua中的内存泄露和我们所说的c/c++中的内存泄露本质上是不一样的。 ? ? ? ? lua中有垃圾回收机制(GC),所以理论上是不会有内存泄露的。当它进行GC的时候,会从根部开始扫描所有的对象,如果某个地方对这个对象还有引用,就不会把这个对象内存collect,这个对象就没有被GC。 ? ? ? ? 所以lua中的内存泄露是指那些:已经没有被使用了,但外部依然还有引用存在的对象。
举个例子:函数中应该被申明为local的对象忘记加local local function test() testTable = {} --这个testTabel会被存放在全局表_G中,GC时由于此对象还有引用存在,所以这里总是会有一个table泄露。 local mt = {} --mt加了local修饰,函数调用完后,引用也不复存在了,GC时会被回收。 setmetatable(testTable,mt) end
?
检测原理: ? ? ? ? lua中支持垃圾回收机制的对象有五种:string,table,function,full userdata,thread。而他们的引用直接或间接的保存到:lua_state对象,_G全局表,Registry注册表,global_state->mt中。
? ? ? ? 在脚本中:
? ? ? ? ? ? ? ? ? ? ? ? ? ?运行的lua脚本本身就是lua_state。
? ? ? ? ? ? ? ? ? ? ? ? ? ?_G就是_G全局表。
? ? ? ? ? ? ? ? ? ? ? ? ? ?Registry表可以用debug.getregistry获取。
? ? ? ? ? ? ? ? ? ? ? ? ? ?global_mt可以用debug.getmetatable获取。
?
? ? ? ? 所以我们就可以在脚本层次实现内存泄露的检测模块。
? ? ? ? 在搜索时需要注意的几点:
? ? ? ? 1、table 额外搜索metatable,若metatable中的__mode取值为”k"、"v"或者”kv"需特殊处理(补充中有说明)
? ? ? ? 2. function 额外搜索 enviroment,也是一个table。额外搜索upvalues,这个可以是任何类型。
? ? ? ? 3. 由于userdata在script层次不能被修改,所以搜搜他的metatable吧
? ? ? ? 4. thread对象就是coroutine对象,在script中一般都不会创建多个coroutine,所以在脚本中没搜索它。若是需求的话,获取到它的线程函数,然后再按照第2步操作就可以了。
?
搜索流程图(_G表):
?
?
在检测泄露之前,先搜索一下所有的对象,保存好起始的内存状态,在程序执行之后执行几次GC操作,然后再进行一次搜索,对比两次的结果,多出来的那些就有可能是内存泄露了。
?
补充:
lua中有一种叫weak表的东东,它的metatable中的__mode被设置为“k","v"或者”kv",表示保存在它中的键或值或键值都是一种弱引用状态。 所以我们可以用另外一种实现:就是把用户自己创建的资源对象统统都丢到weak表中,运行完程序后强制GC,然后去查看weak表,若表中还保存着那个对象,就意味着这个对象还有外部引用(相对弱引用我们就叫它为强引用吧),资源没有被GC掉,所以我们可以说这个对象很有可能是内存泄露了。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |