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
    17
    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"}

泄露检测的思路

  • 把实例化出来的对象丢到 弱引用表 中,一般都会有个最基础的类用于泄露检测或者对象池的操作,与 业务 和 功能 无关,
    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
      7
      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]

参考资料