|
Am 21.05.2014 21:04 schröbte Tim Hill:
On May 20, 2014, at 6:49 PM, Philipp Janda <siffiejoe@gmx.net> wrote:They are collected in the reverse order that they were marked for finalization[1] (usually by setting the metatable), so B will always be collected before A if both become garbage at the same time, because it was created/marked last.I’m not sure this is true; the Lua docs say “in the reverse order they were marked for COLLECTION” (not finalization). So my reading is that the order depends entirely on the order in which the GC determines objects to be unreachable, and (in my reading of it at least) I don’t see a clear guarantee of that ordering in the docs.
Good point. The wording is definitely ambiguous (given that Lua uses a _mark_ and sweep collector) and should be cleared up in the manual.
In any case, imho it’s very bad to depend on the ordering of finalizer calls in any garbage-collected language. If you really have two objects that depend on finalizer ordering then I think you really have a single dispose function that cleans up BOTH at once and can be called from either finalizer, which is much more robust.
It's not just two objects where one depends on the other, but N objects which depend on one other. E.g. in APR you have memory pools that do all the allocation/deallocation of APR objects (files, directories, processes, strings, sockets, etc.), and destroying the pool will destroy all APR objects created with it. The same is true for textures (chunks of memory in video RAM) and renderers in SDL: The renderer destroys all textures that belong to it when it is destroyed, so you must not finalize the renderer before its textures or you will double-free the textures (or crash trying). I also use the finalizer ordering to make sure that `APR_terminate`/`SDL_Quit` is called after all objects from those libraries are destroyed by putting a userdata with a suitable `__gc` in the registry before I initialize the library. Lua itself uses a similar mechanism to ensure that shared libraries are unloaded after all userdata objects using symbols from those libraries are finalized.
—Tim
Philipp