lua中的循环引用辨析

来源:互联网 发布:秦皇岛人人网络 编辑:程序博客网 时间:2024/06/06 18:48

对于任何垃圾收集机制(gc),不可避免的一个问题是循环引用,即:

a引用b,b引用c,c引用a

因为自动收集机制大部分是通过引用计数来完成的,简单的引用机制在上述情况下会歇菜,因为a,b,c都被引用了所以简单的引用机制是不会将他们回收的。

那么lua的gc能不能处理循环引用呢?我们来做一个测试:

--启动gc回收并打印回收结果函数function memColl()print("now collect")collectgarbage("collect")local c1 = collectgarbage("count")print("after collect , mem used is %d", c1)end--开始分配前collectgarbage("collect")local c1 = collectgarbage("count")print("before new, mem used is %d", c1)--开始分配local t = nilfor i = 1, 1000000, 1 do--t通过t.v与t.v.tRef构成循环引用t = {}t.v = {}t.v.tRef = tendlocal c2 = collectgarbage("count")print("after new, mem used is %d", c2)--多次回收memColl()memColl()memColl()memColl()
启动运行查看结果:

可以看到,内存是被回收了的,也就是说lua的gc是能处理循环引用的。


弱引用和循环引用不是一回事,lua中的弱引用有如下好处(摘录自他人的博客):

lua里面也有弱引用,虽然lua的垃圾收集器可以保证没有循环引用的问题,但是lua引用在内存泄漏方面还是有重要意义,在工作实践中,lua的弱引用table(weak table)常被用来检测内存泄漏问题,因为是弱引用并不阻止GC,把要监测的对象放入weak table中,过一段时间,该对象本该要释放,但是在weak table中仍然能检索到此对象,表示此对象泄漏了。演示代码如下:
MemLeakChecker = {}
setmetatable(MemLeakChecker, {__mode="v"})
local Obj = {["Name"] = "Obj1"}
MemLeakChecker["obj1"] = Obj

function DestroyObj()
     Obj = nil
end

DestroyObj()

assert(not MemLeakChecker["obj1"])

 代码其实没有更好的演示出内存泄漏检测的功能,看起来Obj在这里很难泄漏,但是在真正的工作代码中,lua工程常常有成千上万行代码,不同模块有意或无意的引用了一些全局变量,使得GC无法释放,运行久了后,内存消耗巨大,这时使用weak table实时检测跟踪内存泄漏就相当有意义了。 


0 0
原创粉丝点击