lua弱引用检查内存泄漏的简单示例

lua中的内存泄漏和C/C++的内存泄漏概念有一定的区别, 因为lua是具有自动垃圾回收机制的, 当开始GC的时候, 会扫描所有的对象,
将未引用的对象回收. lua的内存泄漏实际是指 : 未使用, 但任然被其他对象所引用的对象, 这些对象没能够被正常销毁.

1
2
3
4
5
local tb1 = {value = 1}
local tb2 = {ref = {tb1}}
tb1 = nil
print("tb1 :", tb1)
print("tb2.ref[1].value :", tb2.ref[1].value)

这一段简单示例代码中tb1被置为nil, 但是内存并没有释放, 因为tb2引用了tb1

利用lua的弱引用功能, 能够帮助我们定位内存泄漏

弱引用设置方式

1
setmetatable({}, {__mode = 'k'}) -- k v kv

弱引用 table 有三种:弱引用 k,弱引用 v 和弱引用 kv。

设置 table 的元表的 __mode 元字段就可以设置一个表为弱引用表,

__mode = k 表示是弱引用 key 表

__mode = v 表示是弱引用 value 表

__mode = kv 表示是弱引用 key-value 表

创建一个gctable, 并设置k为弱引用, 然后每当新创建table时, 就将新建table也向gctable中插入一份, 程序运行结束后, gctable中的就是没有释放的table

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
local gctable = {}
setmetatable(gctable, {__mode = 'k'})

function newtb(default)
local t = default or {}
gctable[t] = true
return t
end

local t1 = newtb {name = 1}
local t2 = newtb {name = 2}
local t3 = newtb {name = 3, ref = {tb1}}

t1 = nil
t2 = nil
collectgarbage("collect")

for k, v in pairs(gctable) do
print("没有释放的table :", k.name)
end