lua中检测内存泄露

本文介绍了如何在Lua中检测内存泄露,尤其是关注lua层中的lua对象泄露。通过使用弱引用,创建一个全局的内存泄露监控表,可以在特定时刻检查对象是否被正确回收。通过测试用例解释了弱引用的工作原理,并展示了简单的内存监控器实现。
摘要由CSDN通过智能技术生成

关于lua中的内存泄露是什么概念,这里就不解释了,请直接百度或者谷歌。

在lua中检测内存泄露,也分两个层次,

层次1:同时检测lua层中的lua对象的泄露和因为lua层而导致的c对象的泄露。

层次2检测lua层中的lua对象的泄露

做到满足层次1的内存泄露检测相对略微复杂,不过原理还是比较简单的,即扫描两个时间点时的lua state并获得快照,之后比较两张快照,后一张中多出来的内存引用就是后一张那个时间点相对前一张那个时间点多分配的内存。那如果这两个时间点在功能逻辑上是一致的(比如前一个时间点是进入某副本前,后一个时间点是退出某副本后),那么多出来的内存引用就是泄露出来的内存。

做到满足层次1的内存泄露检测,这里不做探索。

这里来重点讨论层次2的实现,仅检测lua层中lua对象的泄露这一点也是很重要的。代码规模一大,想通过敏锐的视力和严谨的头脑分析能力来检测出内存泄露是很困难的,因此需要一定的工具来为自己提供帮助。这里可以利用lua提供的“弱引用”,实际上这个概念在刚才给出的第二篇博文里也提到了。“弱引用”是这样的一种引用,其对某个对象的引用并不会对lua gc机制对该对象的垃圾回收造成影响,也就是说某对象若其只存在弱引用,那么该对象会被gc回收——简单来说,gc会无视弱引用。

因此我们可以建立一个全局的内存泄露监控弱引用表,其对键值和内容值的引用为“弱引用”(即其metatable中的__mode元属性值为"kv"),把我们关心的对象放置到该表中。然后等到某一个我们认为此对象应该已经被回收的时刻查看一下该表中是否还存在此对象即可:若不存在,说明该对象被正确的回收了;若存在说明该对象未被正确的回收,简言之,该对象泄露了。

首先来明确弱引用的概念,我们来做几个简单的测试:

--------------------------------

测试用例1:

--内存泄露监控弱引用表
memLeakTbl = {}
setmetatable(memLeakTbl, {__mode = "kv"})

local t1 = {}
print(string.format("tbl t1 is %s", tostring(t1)))

memLeakTbl[t1] = t1
memLeakTbl[1] = {}
t1 = nil

--强制调用gc
print("first time start gc")
collectgarbage("collect")
collectgarbage("collect")
for k, v in pairs(memLeakTbl) do
	print(string.format("%s = %s", tostring(k), tostring(v)))
end

--强制调用gc
print("second time start gc")
collectgarbage("collect")
collectgarbage("collect")
for k, v in pairs(memLeakTbl) do
	print(string.format("%s = %s", tostring(k), tostring(v)))
end

这里的memLeakTbl表其元表__mode = "kv",表示memLeakTbl表的k,v引用均为弱引用。 memLeakTbl中插入两个子表,且这两个子表插入后,除了被该表引用外再也无外接引用,因此代码执行后的输出为:

两趟对memLeakTbl中的遍历输出都显示该表中所有对象已被回收。仅处于弱引用下的对象回收,这正是我们期望的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值