Over the last couple of weeks I have had to solve three fairly major memory leaks that, in the end, were all caused by the same issue so I thought it would be worth mentioning it here to help anyone else who might have the same problems in their code.
One of the things about Garbage Collection is that it appears to be a panacea to finally quash all memory bugs. Unfortunately, it is not! While it is plainly a lot safer and more convenient that having to remember to free objects manually, it is still important to check that one is not leaking memory before releasing anything into the wide world.
I'm my case the issue was to do with using addEventListener() to listen to events from global objects (or at least from objects that were outside the scope of the object doing the listening). I hadn't realized that when using:
xxx:addEventListener("eventName", yyy.func, yyy)
the xxx object will keep a hard link to the yyy object. This will prevent yyy from being garbage collected while xxx remains alive. To use one of @atilim
's demos here is an example:
YYY = Core.class(Sprite)
self.proxy = newproxy(true)
getmetatable(self.proxy).__gc = function() print("collected!") end
XXX:addEventListener(Event.ENTER_FRAME, self.onEnterFrame, self)
-- create an object
XXX = nil
Notice how, even though neither XXX nor YYY are added to the stage, the garbage collector cannot collect YYY until XXX is released.@atilim
, is this what you intended for addEventListener(). My expectation was that it wouldn't keep objects alive. Could you not use a weak link to avoid this?
Anyhow, I hope this might save some other developers a few hours of hair loss if they find they have to track down similar leaks.