luaメモリ検出

6853 ワード

現在担当しているプロジェクトは二次開発プロジェクトであり、私たちに残されたコードの品質は本当にツッコミを入れる力がないため、大小の穴に遭遇し、ゆっくりと流れていった.最近メモリの漏洩の問題に遭遇し、漏洩はluaで発生し、プロジェクトコードには以前の開発チームが漏洩を検出するコードが残っていたが、これに限られている.コード量が膨大なため、どこの引用が乾いていないのか論理的に整理してメモリが漏れているのはほとんど針をすくうことだ.幸いなことに、この文章ではLuaでメモリ漏洩の問題をどのように解決するかについて話します.
メモリの漏洩をどのように発見するかについては、簡単に言えば、見知らぬコードであれば、あるいはあなたのものですが、どこが漏洩しているのか推測するのがおっくうです.雲風の漏洩検査ツールを参照してください.http://blog.codingnow.com/2012/12/lua_snapshot.html
コードの一般的な論理が熟知している場合は、弱い参照テーブルを使用して、漏洩の有無を確認できます.通常、漏れが発生するのは、ゲーム内のモンスター(死んだら新しいものをブラシする)、プレイヤー(誰かがログインして新しいプレイヤーオブジェクトを作成する)、プログラムの実行サイクル中に繰り返し作成、破棄するため、きれいに破壊されない場合、明らかなメモリ漏れを招きやすいタイプです.これらのオブジェクトに漏れがあるかどうかを調べるには、弱い参照テーブルという簡単な方法があります.(弱引用とは何か分からない場合は、ここをクリックしてください).
メモリの漏洩を発見するために、グローバルな弱い参照tableを作成し、keyを弱い参照にすることができます.その後、漏洩の可能性があるオブジェクトを作成するたびに、このtableを入れてkeyとして使用します.valueは通常、現在の時間を使用します.弱い参照の性質のため、他の参照が消えた場合、弱い参照tableではこのオブジェクトへの参照も消え(nilになります)、逆に、他のいずれかの参照が存在する限り、この弱い参照テーブルではこのオブジェクトへの参照は引き続き存在します.この特性に依存して、プログラムがオブジェクトを解放する論理を走った後、このテーブルにこのオブジェクトの参照が存在する場合、このオブジェクトは漏れているに違いありません.
漏れを発見する方法を話して、次はどのように解決する番ですか.実は私ももともと雲大のsnapshotを試してみたいと思っていましたが、このプロジェクトはluajitを使っていて、わけがわからずrequireができなくて、時間が迫っていて、研究できなくて、やめて、別の方法を探すしかありません.意外にもGoogleではsnapshot以外に似たような解決策はほとんどありません.急いで、原理を研究して、自分で手を出して、次は乾物を見てください.
メモリの漏洩が必ず参照されていない以上、luaの特性に基づいて、この参照は必ず_Gの次のいずれかのtableやfunctionのupvalueでは(これを理解していない学生は理解してから下を見てください)、第一歩の方法で漏れを特定することができ、漏れ対象の引用を得ることができる以上、事はずっとやりやすいです.引用を得て遍歴するにほかならない.G、この引用を見つけて、階層を並べて、これがどこにあるのかを簡単に知ることができて、解決したいと思っています.実装方法はあまり言わないで、コードが最も直接的であることを見ます.次のコードではfindObjectInGlobal(漏洩オブジェクトの参照)を呼び出すと、すべての非局所変数の帰属関係が見つかります.
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 or value == obj then  
                _info("Finded Object")  
                return true  
            end  
            if findObject(obj, key) == true then  
                _info("table key")  
                return true  
            end  
            if findObject(obj, value) == true then  
                _info("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  
                _info("upvalue name:["..tostring(name).."]")  
                return true  
            end  
            uvIndex = uvIndex + 1  
        end  
    end  
    return false  
end  

function _G.findObjectInGlobal(obj)  
    findedObjMap = {}  
    setmetatable(findedObjMap, {__mode = "k"})  
    _G.findObject(obj, _G)  
end