Lua中的弱引用,类似C#中的 WeakReference,可以判断对象是否存活,进而判断是否有泄露
Lua弱引用表
table 中的的key或者value如果不想引用住赋值进来的对象(其实就是table)的话,只需要一行代码
setmetatable(objTab, {__mode = "k"});
,测试代码如下,local 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"}
)
- objTab 将print不出任何东西,是因为 objTab 中的 key或者value 被回收掉,为nil值,所以不会遍历出来。(如果想value也为弱引用的话这里改为
泄露检测的思路
把实例化出来的对象丢到 弱引用表 中,一般都会有个最基础的类用于泄露检测或者对象池的操作,与 业务 和 功能 无关,
-- 简易版对象 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
- 结果
false
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]
- 结果