Memory leak

I have a small memory leak and im not sure whats causing it.  If anyone could help me that would be great.

I am using this function to monitor my memory.

local monitorMem = function() collectgarbage() print( "MemUsage: " .. collectgarbage("count") ) local textMem = system.getInfo( "textureMemoryUsed" ) / 1000000 print( "TexMem: " .. textMem ) end Runtime:addEventListener( "enterFrame", monitorMem )

timeAttack.lua

local storyboard = require( "storyboard" ) local scene = storyboard.newScene() --Up Values local centerXcord = display.contentCenterX --Center X cord local centerYcord = display.contentCenterY --Center Y cord local \_W = display.contentWidth local \_H = display.contentHeight local mRand = math.random local timeLimit = 5; --Decreases timer by 1 every 1 second. If timer runs out then show game over. local function timerDown() timeLimit = timeLimit - 1 timeLeft.text = timeLimit if timeLimit == 0 then storyboard.gotoScene( "scenes.gameOverTimeAttack" ) end end local function spawnOrb() orb = display.newRect(0, 0, 64, 64) orb.x = mRand(32, \_W - 32) orb.y = mRand(32, \_H - 32) function orb:touch(e) if (e.phase == "began") then orbsKilledText.text = orbsKilledText.text + 1 --Update Score orb:removeSelf() --Remove Object spawnOrb() --Restart The Function end end orb:addEventListener( "touch", orb ) end --If play button is touched then play game local function startGame( self, event ) if event.phase == "began" then spawnOrb() --Start Showing Orbs local t = timer.performWithDelay(1000,timerDown,timeLimit) --Start the time limit startButton:removeSelf() --Remove Start Button startButton = nil end return true end -- Called when the scene's view does not exist: function scene:createScene( event ) local screenGroup = self.view startButton = display.newImage( "images/button.png" ) startButton.x = centerXcord startButton.y = centerYcord screenGroup:insert( startButton ) startButton.touch = startGame startButton:addEventListener( "touch", startButton ) local startText = display.newText(0, 0, 0, native.systemFont, 32) startText.text = "Start" startText.x = centerXcord startText.y = centerYcord startText:setFillColor( black ) screenGroup:insert( startText ) local TorbsKilledText = display.newText(0, 0, 0, native.systemFont, 32) TorbsKilledText.text = "Orbs Broken:" TorbsKilledText.x = centerXcord TorbsKilledText.y = \_H - \_H + 32 screenGroup:insert( TorbsKilledText ) orbsKilledText = display.newText(0, 0, 0, native.systemFont, 32) orbsKilledText.text = 0 orbsKilledText.x = centerXcord + 150 orbsKilledText.y = \_H - \_H + 32 screenGroup:insert( orbsKilledText ) local timeLeftText = display.newText(0, 0, 0, native.systemFont, 32) timeLeftText.text = "Time Remaining:" timeLeftText.x = \_W - 220 timeLeftText.y = \_H - \_H + 32 screenGroup:insert( timeLeftText ) timeLeft = display.newText(0, 0, 0, native.systemFont, 32) timeLeft.text = timeLimit timeLeft.x = \_W - 64 timeLeft.y = \_H - \_H + 32 screenGroup:insert( timeLeft ) end -- Called immediately after scene has moved onscreen: function scene:enterScene( event ) local screenGroup = self.view storyboard.removeAll( ) end -- Called when scene is about to move offscreen: function scene:exitScene( event ) local screenGroup = self.view orb:removeSelf() --Remove Object orb = nil orbsKilledText:removeSelf() timeLeft:removeSelf() end -- Called prior to the removal of scene's "view" (display group) function scene:destroyScene( event ) local screenGroup = self.view print "Scene Destroyed" end -- "createScene" event is dispatched if scene's view does not exist scene:addEventListener( "createScene", scene ) -- "enterScene" event is dispatched whenever scene transition has finished scene:addEventListener( "enterScene", scene ) -- "exitScene" event is dispatched before next scene's transition begins scene:addEventListener( "exitScene", scene ) -- "destroyScene" event is dispatched before view is unloaded, which can be -- automatically unloaded in low memory situations, or explicitly via a call to -- storyboard.purgeScene() or storyboard.removeScene(). scene:addEventListener( "destroyScene", scene ) --------------------------------------------------------------------------------- return scene

gameOver.lua

-- require controller module local storyboard = require( "storyboard" ) --Up Values local scene = storyboard.newScene() local centerXcord = display.contentCenterX --Center X cord local centerYcord = display.contentCenterY --Center Y cord local \_W = display.contentWidth local \_H = display.contentHeight local stats = 0 local function checkData() stats = stats + orbsKilledText.text end checkData() --Save data local function saveData () if stats \> myGameStats.timeAttack then myGameStats.timeAttack = stats end saveTable(myGameStats, "mygamestats.json") end saveData () --If play button is touched then play game local function retryButton( self, event ) if event.phase == "began" then storyboard.gotoScene( "scenes.timeAttack", "fade", 400 ) end return true end -- Called when the scene's view does not exist: function scene:createScene( event ) local screenGroup = self.view local bgImage= display.newImage( "images/bgImage.png" ) bgImage.x = centerXcord bgImage.y = centerYcord bgImage.width = \_W bgImage.height = \_H screenGroup:insert( bgImage ) local gameOverText = display.newText(0, 0, 0, native.systemFont, 96) gameOverText.text = "Game Over" gameOverText.x = centerXcord gameOverText.y = centerYcord - 300 gameOverText:setFillColor( black ) screenGroup:insert( gameOverText ) local retry = display.newImage( "images/button.png" ) retry.x = centerXcord retry.y = centerYcord + 300 screenGroup:insert( retry ) retry.touch = retryButton retry:addEventListener( "touch", retry ) local retryText = display.newText(0, 0, 0, native.systemFont, 32) retryText.text = "Retry" retryText.x = centerXcord retryText.y = centerYcord + 300 retryText:setFillColor( black ) screenGroup:insert( retryText ) local scoreText = display.newText(0, 0, 0, native.systemFont, 32) scoreText.text = "Score:" scoreText.x = centerXcord scoreText.y = centerYcord scoreText:setFillColor( black ) screenGroup:insert( scoreText ) local score = display.newText(0, 0, 0, native.systemFont, 32) score.text = orbsKilledText.text score.x = centerXcord + 80 score.y = centerYcord score:setFillColor( black ) screenGroup:insert( score ) end -- Called immediately after scene has moved onscreen: function scene:enterScene( event ) local screenGroup = self.view end -- Called when scene is about to move offscreen: function scene:exitScene( event ) local screenGroup = self.view storyboard.removeAll( ) orbsKilledText = nil end -- Called prior to the removal of scene's "view" (display group) function scene:destroyScene( event ) local screenGroup = self.view print "Scene Destroyed" end -- "createScene" event is dispatched if scene's view does not exist scene:addEventListener( "createScene", scene ) -- "enterScene" event is dispatched whenever scene transition has finished scene:addEventListener( "enterScene", scene ) -- "exitScene" event is dispatched before next scene's transition begins scene:addEventListener( "exitScene", scene ) -- "destroyScene" event is dispatched before view is unloaded, which can be -- automatically unloaded in low memory situations, or explicitly via a call to -- storyboard.purgeScene() or storyboard.removeScene(). scene:addEventListener( "destroyScene", scene ) --------------------------------------------------------------------------------- return scene

try putting a short delay (timer.performWithDelay) after you ‘object:removeSelf()’ and creating the same object again. I know this is needed for displayGroups.

For example (you need to do this for the other objects too) :

local function spawnOrb() orb = display.newRect(0, 0, 64, 64) orb.x = mRand(32, \_W - 32) orb.y = mRand(32, \_H - 32) function orb:touch(e) if (e.phase == "began") then orbsKilledText.text = orbsKilledText.text + 1 --Update Score orb:removeSelf() --Remove Object local timerID = timer.performWithDelay( 10, spawnOrb ) --Restart The Function end

Thank you ill give it a try.

that’s a lot of code to wade through, and i only scanned the first screenfull, but noticed “orb” has an addEventListener without an explicit remove in its touch handler when destroyed, perhaps a place to start? (that local function may have a lingering reference in the event dispatcher, so each new instance would leak)

I thought touch listeners attached to a object are auto removed via storyboard or is that only if the object is in the displaygroup? So every time i destroy the object i should remove the listener and add it again when the spawn orb function runs?

was only meant as a suggestion to get you started (restructuring that local listener and such) with that much code posted, it didn’t seem like you’d narrowed it down much yet. if looking for a place to start, try making sure everything that CAN be explicit, IS explicit. (that’d include all the local display objects in your scene create’s too)

re orb spawning (not that I know it’s leaking – I do not, but just how you maybe could do things differently): all it seems to do (remember, I’ve not actually run your code) is move around a single rect. Why not create it once and assign listener once, and just change it’s x/y on touch, over and over again reusing same rect? I see a lot of work going on there, for seemingly little reason, that’s why it just looked “suspicious”.

if you can simplify parts of it to the point where you know they’re not the leak, then you’ll at least have narrowed down the problem a bit. you’ll get better help from forum if you can get it down to a “somewhere in these 20-or-so lines is a leak” -type scenario

hth

Ok thanks for the advice.

Just want to say thanks. You were absolutely right the function i was using to create the orbs was way over complicated. I took your advice and instead moved the object rather than creating a new one. I started to break my code down little by little and found my issues. When im programming for hours on end and stuck on a specific idea I tend to make things more complicated than they need to be. Thanks for your advice it helped me improve.

try putting a short delay (timer.performWithDelay) after you ‘object:removeSelf()’ and creating the same object again. I know this is needed for displayGroups.

For example (you need to do this for the other objects too) :

local function spawnOrb() orb = display.newRect(0, 0, 64, 64) orb.x = mRand(32, \_W - 32) orb.y = mRand(32, \_H - 32) function orb:touch(e) if (e.phase == "began") then orbsKilledText.text = orbsKilledText.text + 1 --Update Score orb:removeSelf() --Remove Object local timerID = timer.performWithDelay( 10, spawnOrb ) --Restart The Function end

Thank you ill give it a try.

that’s a lot of code to wade through, and i only scanned the first screenfull, but noticed “orb” has an addEventListener without an explicit remove in its touch handler when destroyed, perhaps a place to start? (that local function may have a lingering reference in the event dispatcher, so each new instance would leak)

I thought touch listeners attached to a object are auto removed via storyboard or is that only if the object is in the displaygroup? So every time i destroy the object i should remove the listener and add it again when the spawn orb function runs?

was only meant as a suggestion to get you started (restructuring that local listener and such) with that much code posted, it didn’t seem like you’d narrowed it down much yet. if looking for a place to start, try making sure everything that CAN be explicit, IS explicit. (that’d include all the local display objects in your scene create’s too)

re orb spawning (not that I know it’s leaking – I do not, but just how you maybe could do things differently): all it seems to do (remember, I’ve not actually run your code) is move around a single rect. Why not create it once and assign listener once, and just change it’s x/y on touch, over and over again reusing same rect? I see a lot of work going on there, for seemingly little reason, that’s why it just looked “suspicious”.

if you can simplify parts of it to the point where you know they’re not the leak, then you’ll at least have narrowed down the problem a bit. you’ll get better help from forum if you can get it down to a “somewhere in these 20-or-so lines is a leak” -type scenario

hth

Ok thanks for the advice.

Just want to say thanks. You were absolutely right the function i was using to create the orbs was way over complicated. I took your advice and instead moved the object rather than creating a new one. I started to break my code down little by little and found my issues. When im programming for hours on end and stuck on a specific idea I tend to make things more complicated than they need to be. Thanks for your advice it helped me improve.