lua-Lua弱引用及泄露检测
Lua中的弱引用,类似C#中的 WeakReference,可以判断对象是否存活,进而判断是否有泄露
Lua弱引用表
- table 中的的key或者value如果不想引用住赋值进来的对象(其实就是table)的话,只需要一行代码
setmetatable(objTab, {__mode = "k"});
,测试代码如下,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17local function TestWeakRef( )
local objTab = {}
setmetatable(objTab, {__mode = "k"}); -- 设置 objTab 中的 key 为弱引用
local gTab = nil
for i=1,5 do
local tab1 = { key1 = "aaa"}
objTab[tab1] = i
-- gTab = tab1 -- 强引用
end
collectgarbage("collect") -- 强制垃圾回收
for k,v in pairs(objTab) do
print(k, v)
end
end - objTab 将print不出任何东西,是因为 objTab 中的 key或者value 被回收掉,为nil值,所以不会遍历出来。(如果想value也为弱引用的话这里改为
__mode = "kv"}
)
泄露检测的思路
- 把实例化出来的对象丢到 弱引用表 中,一般都会有个最基础的类用于泄露检测或者对象池的操作,与 业务 和 功能 无关,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34-- 简易版对象
local CObjBase = {}
CObjBase.__index = CObjBase
CObjBase.New = function(self)
local t = {}
self._alive = true
self._stackInfo = debug.traceback("", 1) -- 可以加入一些堆栈信息,正式版需要去掉这些无用调试信息
setmetatable(t, CObjBase)
return t
end
CObjBase.Destroy = function(self)
self._alive = false -- 主动销毁标记
end
local function TestWeakRef( )
local objTab = {}
setmetatable(objTab, {__mode = "k"}); -- 设置 objTab 中的 key 为弱引用
local gTab = nil
for i=1,5 do
local tab1 = CObjBase:New() -- 模拟实例化一个对象
setmetatable(tab1, CObjBase);
tab1:Destroy()
objTab[tab1] = i
gTab = tab1 -- 模拟某一地方强引用造成,泄露
end
collectgarbage("collect") -- 强制垃圾回收
for k,v in pairs(objTab) do
print(k._alive, k._stackInfo) -- 如果存在的对象的 _alive 标记为 false,这说明该该对象泄露了
end
end- 结果
1
2
3
4
5
6
7false
stack traceback:
F:\lua-5.3.0\aaa.lua:93: in method 'New'
F:\lua-5.3.0\aaa.lua:104: in local 'TestWeakRef'
F:\lua-5.3.0\aaa.lua:127: in main chunk
[C]: in ?
[Finished in 0.1s]
- 结果