Nic*_* M. 17 lua garbage-collection
我曾经遇到过几个 地方,人们称之为collectgarbage() 两次来完成所有未使用的对象.
这是为什么?为什么单个电话不够?为什么不打三个电话?
当我尝试下面的代码(在Lua 5.2上)时,__gc
只需一次调用就可以最终确定对象(意思是:它被调用)collectgarbage
:
do
local x = setmetatable({},{
__gc = function() print("works") end
})
end
collectgarbage()
os.exit()
Run Code Online (Sandbox Code Playgroud)
这是否意味着一个电话就足够了?
Yu *_*Hao 16
它在Lua第3版§17.6终结器编程中进行了解释.简而言之,这是因为复活.
终结器是与将要收集该对象时调用的对象相关联的函数.Lua使用__gc
metamethod 实现终结器.
问题是,当调用终结器时,在某些情况下对象必须是活的.PiL用这个例子解释了它:
Run Code Online (Sandbox Code Playgroud)A = {x = "this is A"} B = {f = A} setmetatable(B, {__gc = function (o) print(o.f.x) end}) A, B = nil collectgarbage() --> this is A
B
访问的终结器A
,因此A
无法在最终确定之前收集B
.Lua中必须既复活B
和A
运行终结之前.
复活是collectgarbage
两次召唤的原因:
由于复活,具有终结器的物体分两个阶段收集.收集器第一次检测到具有终结器的对象无法访问时,收集器会重新生成对象并对其进行排队以进行最终确定.一旦终结器运行,Lua就会将对象标记为已完成.下次收集器检测到对象不可访问时,它会删除该对象.如果要确保程序中的所有垃圾都已实际释放,则必须调用
collectgarbage
两次; 第二个调用将删除第一次调用期间最终确定的对象.