Memory Leak when switching scenes

I noticed that I have a memory leak in my level selection scene.  Every time I leave and come back to the scene, the memory usage goes up some and continues to do so each time I come back to the scene. 

I was able to fix this by completely removing the scene in the scene:hide, phase==“did” section.

composer.removeScene("scripts.level\_select")

I presume this means I must have forgotten to add some display objects to the sceneGroup? 

Would there be any other cause of a memory leak besides forgetting to add something to the sceneGroup?

Most common types of memory leaks occur from the use of globals or from incorrectly clearing variables that are no longer used.

Now, what is your memory use when you move in and out of the scene repeatedly? Sure, it rises and drops, but does it rise to the same level or does it keep increasing every time?

When you say globals, are you referring to variables where I don’t declare local in front?  Because I have a module I am using for “global” variables that I require at the top of my code and then pull values from.  Example:  my_globals = require"my_globals" 

and then in my code later I’m doing   my_globals.player_speed , etc etc.  

Would anything with that cause a leak?

The first time I enter the scene:

MemUsage:    1145

TexMem:   14.9

2nd time:

MemUsage:   1164

TexMem:  15.09

3rd time:

MemUsage:   1170

TexMem:  15.23

4th time:

MemUsage:   1174

TexMem:     15.36

etc etc…

I have went through line by line and commented out various sections to try to see if I can lower it.  It was leaking much more and then I found 1 runtime listener I hadn’t been cancelling which helped.  But at this point I think I have gone through every single variable, display object, listener, and timer and I don’t know what would be causing the small leak that’s still left. 

Yes, global variables are variables that aren’t explicitly local. If you were to create display objects like:

object = display.newRect( 100, 100, 100, 100 ) object = display.newRect( 100, 100, 100, 100 )

Then you will lose your reference to the former object and it’ll be difficult to get rid of it.

If you require modules as globals, and those modules themselves have globals in them, then you again run the risk of creating memory leaks.

Okay, now that I understand what you meant, I can safely say I have NOT used global variables anywhere.  All of my variables in “my_globals”  are locally declared inside that module. 

I have went through the normal checklist of following:

  1. Display objects are part of sceneGroup 

  2. All timers and transitions that I can see have been stored, cancelled, and set to nil upon leaving the scene.

  3. All event listeners have been removed upon leaving the scene

  4. I have not used any global variables. 

If I have went through this list exhaustively and am still getting a slight leak, what next steps can I take to try to find the culprit?

Are there multiple objects being created and destroyed?  Are there tables you are using to track the objects?

Yes, multiple enemies being created and destroyed.  Enemies are added to a table when created and I loop through the table in my destroy function before switching scenes.  Posting some sample code from my destroy function:

local function destroy() for i = 1, #all\_timers do timer.cancel(all\_timers[i]) all\_timers[i] = nil end for i = 1, #all\_transitions do transition.cancel(all\_transitions[i]) all\_transitions[i] = nil end display.remove(cd\_box) cd\_box = nil for i = 1, #cd\_slices do --print("removing slice # " .. i) display.remove(cd\_slices[i]) cd\_slices[i] = nil end cd\_slices = {} display.remove(game\_lost\_splat) game\_lost\_splat = nil camera.detach() player:goodBye() Runtime:removeEventListener("updateLives", scene) Runtime:removeEventListener("addTime", scene) Runtime:removeEventListener("takeDamage", scene) Runtime:removeEventListener("gameWon", scene) Runtime:removeEventListener("gameLost", scene) Runtime:removeEventListener("gotGoldGrape", scene) map = {} map = nil mapData = {} mapData = nil world = {} content = {} world = nil content = nil if(ability\_rect.\_functionListeners.touch)then ability\_rect:removeEventListener("touch", abilityTouched) end if(countDownTimer ~= nil) then timer.cancel(countDownTimer) countDownTimer = nil end if(cd\_timer ~= nil) then timer.cancel(cd\_timer) cd\_timer = nil end for i = 1, #random\_enemies do for j = 1, #random\_enemies[i] do random\_enemies[i][j]:goodBye() end random\_enemies[i] = {} end random\_enemies = {} end