I have encountered several places where people call collectgarbage() twice to finalize all unused objects.
Why is that? Why isn't a single call enough? Why not three calls?
When I try the following code (on Lua 5.2), the object gets finalized (meaning: its __gc
gets called) with just a single call to collectgarbage
:
do
local x = setmetatable({},{
__gc = function() print("works") end
})
end
collectgarbage()
os.exit()
Does this mean one call is enough?
Lua uses a garbage collector that runs from time to time to collect dead objects when they are no longer accessible from the Lua program. All objects including tables, userdata, functions, thread, string and so on are subject to automatic memory management.
Lua does automatic memory management. A program only creates objects (tables, functions, etc.); there is no function to delete objects. Lua automatically deletes objects that become garbage, using garbage collection.
It's explained in Programming in Lua 3rd edition §17.6 Finalizers. In short, it's because of resurrection.
A finalizer is a function associated with an object that is called when that object is about to be collected. Lua implements finalizers with __gc
metamethod.
The problem is, when the finalizers are called, the object must be alive in some cases. PiL explains it with this example:
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
The finalizer for
B
accessesA
, soA
cannot be collected before the finalization ofB
. Lua must resurrect bothB
andA
before running that finalizer.
Resurrection is the reason of calling collectgarbage
twice:
Because of resurrection, objects with finalizers are collected in two phases. The first time the collector detects that an object with a finalizer is not reachable, the collector resurrects the object and queues it to be finalized. Once its finalizer runs, Lua marks the object as finalized. The next time the collector detects that the object is not reachable, it deletes the object. If you want to ensure that all garbage in your program has been actually released, you must call
collectgarbage
twice; the second call will delete the objects that were finalized during the first call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With