How to deal with Lua Memory leakage and lua Leakage
Currently, the project in charge is a secondary development project, and the quality of the Code left for us is really boring, so we have encountered a lot of big and small pitfalls, but it is good to be slow. Recently I encountered a memory leakage problem, which occurs in lua. The previous development team in the project code left the code to detect the leakage, but it is also limited to this. Because of the huge amount of code, it is almost a haystack to find out logically where the reference is not killed, resulting in Memory leakage. Fortunately, the solution is smooth. This article will talk about how to solve the memory leakage problem in Lua.
As for how to detect memory leakage, let's also briefly talk about it. If it's a strange code, or even though it's yours, but you are too lazy to guess where it is leaked, please refer to the cloud wind leak detection tool: http://blog.codingnow.com/2012/12/lua_snapshot.html
If the general logic of the Code is familiar, you can use a weak reference table to check whether there is any leakage.Leakage is usually caused by repeated creation types.For example, the monsters in the game (click a new one when they are killed) and players (when someone logs on, a new player object will be created ), because these things are repeatedly created and destroyed during the program running cycle, once the destruction is not clean, it is easy to cause obvious Memory leakage. To check whether these objects are leaked, there is a simple method:Weak reference table. (If you do not know what weak references are, click here ).
To detect memory leakage, we canCreate a global weak reference table so that its key is weak referenceAnd then put the table into every creation of objects that may leak, so that it serves as the key. The value usually uses the current time. Due to the nature of weak references, if other references disappear, the references to this object in the weak reference table will also disappear (to nil). Otherwise, as long as any other reference exists, the reference to this object in this weak reference table will continue to exist. Depending on this feature, when the program has run the logic of releasing an object, if this table still has reference to this object, this object will surely be leaked.
After talking about how to find the leak, it is the next step to solve it. As a matter of fact, I also wanted to try the snapshot of the cloud, but this project uses luajit. Somehow, it cannot be require. It is time-consuming and cannot be studied. I have to leave it alone and find another method. There is almost no decent solution except snapshot. In a hurry, I had to study the principle and do it myself. Please take a look at the following:
Since there must be some reference for memory leaks, based on the features of lua, this reference must exist in upvalue of a table or function under _ G (if you do not want to understand this, please try again). Since the first step can be used to locate the leakage, in addition, you can get reference of the leaked object, so it is much easier to do. It is nothing more than traversing _ G after obtaining the reference, finding the reference, and listing the level, so that you can easily know where this thing is, and it is much easier to solve it. There is not much to say about the implementation method. It is the most direct way to look at the code. In the following code, you can call findObjectInGlobal to find the ownership of all non-local variables.
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 falseendfunction _G.findObjectInGlobal(obj) findedObjMap = {} setmetatable(findedObjMap, {__mode = "k"}) _G.findObject(obj, _G)end