利用弱引用检查内存泄露

  在进一步优化公司项目的时候发现,我们项目在开始游戏进入主城的时候lua占用内存是45.0M,C#占用内存9.6M,而随着多次游戏再返回主城之后,lua的内存占用有时候能高达140M(多了100M),很显然是发生了内存泄露,这里介绍一个检查内存泄露的工具供大家使用,我加了一点注释和修改更方便理解

--这是lua代码
--初始化内存泄露监视表
function initMemoryTable()
    t_memoryTable = {}  
    setmetatable(t_memoryTable, {__mode = "k"})  
end

--把一个对象放入内存监视表
function putOneObjeatInMemoryTable( x_someThing,x_id )
    if x_someThing ~= nil then
        t_memoryTable[x_someThing] = x_id;
    end
end

--显示所有没有被释放的对象(仅判断在内存监视表中的对象)
function showTheMrmoryTable()
    local n_count = 0;
    for k,v in pairs(t_memoryTable) do
        n_count =n_count + 1;
        warn("id: "..tostring(v).." obj: "..tostring(k));
        _G.findObjectInGlobal(k) 
    end
end


local findedObjMap = nil   
--递归地从某位置寻找某一个对象,并自动从其子节点继续寻找
function _G.findObject(obj, findDest)  
    if findDest == nil then  
        return false  
    end  
    if findedObjMap[findDest] ~= nil then  
        return false  
    end  
    findedObjMap[findDest] = true  

    local destType = type(findDest)  
    if destType == "table" then  
        if findDest == _G.CMemoryDebug then  
            return false  
        end  
        for key, value in pairs(findDest) do  
            if key == obj then  
                warn("Finded Object: key == obj")  
                return true  
            end  

            if value == obj then  
                warn("Finded Object key:["..tostring(key).."]")  
                return true  
            end 

            if findObject(obj, key) == true then  
                warn("table key")  
                return true  
            end  
            if findObject(obj, value) == true then  
                warn("key:["..tostring(key).."]")  
                return true  
            end  
        end  
    elseif destType == "function" then  

        local uvIndex = 1  
        while true do  
            local name, value = debug.getupvalue(findDest, uvIndex)  
            if name == nil then  
                break  
            end  

            if findObject(obj, value) == true then  
                warn("upvalue name:["..tostring(name).."]")  
                return true  
            end  
            uvIndex = uvIndex + 1  
        end  
    end  
    return false  
end

--从G表中寻找某一个对象,并打印其位置
function _G.findObjectInGlobal(obj)  
    findedObjMap = {}  
    setmetatable(findedObjMap, {__mode = "k"})  
    if _G.findObject(obj, _G)  == true then
        warn("in _G");
    end
end 

这个工具的原理 参考文章

kisence

潮落江平未有风。