转自http://blog.csdn.net/xocoder/article/details/42685685

由于目前正在负责的项目是一个二次开发项目,而且留给我们的代码质量实在让人无力吐槽,所以遇到了不少大大小小的坑,好在慢慢都淌过去了。最近就遇到了一个内存泄漏的问题,泄漏发生在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 =
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 +
end
end
return false
end function _G.findObjectInGlobal(obj)
findedObjMap = {}
setmetatable(findedObjMap, {__mode = "k"})
_G.findObject(obj, _G)
end

Lua内存泄漏应对方法[转]的更多相关文章

  1. [Lua]内存泄漏与垃圾回收

    参考链接: http://colen.iteye.com/blog/578146 一.内存泄漏的检测 Lua的垃圾回收是自动进行的,但是我们可以collectgarbage方法进行手动回收.colle ...

  2. iOS AFNetworking内存泄漏处理方法

    iOS AFN内存泄漏处理方法 细心的你是否也发现AFN的内存泄漏的问题了呢. 在这里给大家提供一个解决AFN内存泄漏的方法. 单例解决AFN内存泄漏 + (AFHTTPSessionManager ...

  3. C++程序内存泄漏检测方法

    一.前言 在Linux平台上有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器,再加上它的开源属性,相对而言,处理问题容易形成“统一”的标准.而在W ...

  4. VS2005内存泄漏检测方法[转载]

    一.非MFC程序可以用以下方法检测内存泄露: 1. 程序开始包含如下定义: #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __ ...

  5. Android内存管理(5)*官方教程:Logcat内存日志各字段含义,查看当前内存快照,跟踪记录内存分配,用adb查看内存情况时各行列的含义,捕获内存快照的3种方法,如何让程序暴漏内存泄漏的方法

    Investigating Your RAM Usage In this document Interpreting Log Messages                 内存分析日志中各消息的含 ...

  6. Chrome JS内存泄漏排查方法(Chrome Profiles)

     原文网址:http://blog.csdn.net/kaitiren/article/details/19974269 JS内存泄漏排查方法(Chrome Profiles)   Google Ch ...

  7. 关于 Lua 内存泄漏的检测

    前一阵开始和同事一起优化内存,首先是优化 Lua 内存,因为发现每次战斗完后 Lua 内存非常大,从 3M 左右在经过了10次左右的战斗后,会暴增到近 100M,很明显是有内存泄漏.      然后我 ...

  8. VS2005 检测内存泄漏的方法(转载)

    一.非MFC程序可以用以下方法检测内存泄露: 1.程序开始包含如下定义: #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __F ...

  9. C++程序在Windows平台上各种定位内存泄漏的方法,并对比了它们的优缺点

    一.前言 在Linux平台上有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器,再加上它的开源属性,相对而言,处理问题容易形成“统一”的标准.而在W ...

随机推荐

  1. IE常见的CSS的BUG(一)

    2011年6月,我毕业了.2012年我接触了CSS,本以为会好过些能赚点钱了,可谁知,Internet Explorer(下称IE),这个前端工程师的噩梦浏览器让我不再那么好过了.各种出现在IE身上的 ...

  2. [Regular Expressions] Introduction

    var str = "Is this This?"; //var regex = new RegExp("is", "gi"); var r ...

  3. JavaScript总结(二) 系统分析

    学习Javascript的时候.遇到了一个问题. 看了牛腩的视频,感觉讲的太简单和基础,像认识一位新朋友.但仅有一面之缘就结束了. 再看姜浩的视频.又看得迷迷糊糊,让我找到了当初看两位台湾专家讲VB. ...

  4. 前端--关于HTML

    在讲HTML之前不得不先简单粗略提一下浏览器以及浏览器与HTML的关系.众所周知,浏览器就是一个应用程序,这个应用程序可以完成网络调用.展示接收的html文档等.严格来讲HTML文档就是按照某个规则写 ...

  5. FpSpread添加表头(列名)标注

    for (int j = 0; j < fp.ActiveSheetView.ColumnCount; j++) { fp.ActiveSheetView.ColumnHeader.Cells[ ...

  6. va_list/va_start/va_arg/va_end深入分析

    http://www.cnblogs.com/justinzhang/archive/2011/09/29/2195969.html

  7. cell的各种使用和赋值 总结

    cell可以分为:自定义cell,系统的cell ,cell的自适应,.xib的cell //第一种cell:系统cell 在 UIViewController下创建UITableView //1.0 ...

  8. K-D Tree题目泛做(CXJ第二轮)

    题目1: BZOJ 2716 题目大意:给出N个二维平面上的点,M个操作,分为插入一个新点和询问到一个点最近点的Manhatan距离是多少. 算法讨论: K-D Tree 裸题,有插入操作. #inc ...

  9. 慕课linux学习笔记(二)Xshell与虚拟机的连接

    选择使用的是Xshell5 新建连接 连接成功 修改编码方式,字号,颜色 PS: 连接过程中遇到了很多问题,虚拟机的网络连接我最初选择的是桥连,虚拟机和主机相互之间都能ping通但Xshell就是连接 ...

  10. ACM训练计划step 2 [非原创]

    (Step2-500题)POJ训练计划+SGU 经过Step1-500题训练,接下来可以开始Step2-500题,包括POJ训练计划的298题和SGU前两章200题.需要1-1年半时间继续提高解决问题 ...