Do director class set nil to all the objects from last scene?
When I get out of an scene and enter another, I see an relative grow in the memory used. I turn off all the event listeners, so I don’t know the problem here…
Some suggestions?
Thanks.
Do director class set nil to all the objects from last scene?
When I get out of an scene and enter another, I see an relative grow in the memory used. I turn off all the event listeners, so I don’t know the problem here…
Some suggestions?
Thanks.
Unfortunately, until there’s a new kid on the block, for both Director and Storyboard, you’re responsible for making sure all display objects, timers, and transitions are properly removed, canceled, and nil’ed before exiting a scene.
I would suggest tying all timers and transitions to the object you’re working with, like this:
object.timer = timer.performWithDelay( 1000, moveObjectFunction, 0 ) object.trans = transition.to( object, { time = 500, alpha = 0, onComplete = function() resetAlpha( object ) end } ) ... timer.cancel( object.timer ) transition.cancel( object.trans ) display.remove( object ) object = nil
Maybe that’s it, because I don’t set nil to all my objects.
Is there a large difference between
display.remove(object)
and
object:removeSelf()
?
What if I use the following?
localGroup:removeSelf(); localGroup = nil;
The localGroup contains all my objects.
removeSelf brings back some bad memories for me. When I used to use it, I had to perform a check, or Corona would crash:
if object and object.removeSelf then object:removeSelf() object = nil end
Now, I just use this:
display.remove( object ) object = nil
Works regardless if it was a displayObject or if it was partially deleted (or is being concurrently deleted) by another function. I believe you could do localGroup:removeSelf(), but I believe there is also unloadScene and localGroup:clean() in Director as well. Best to experiment and see if the memory is getting cleared by performing a memory check before and after you do your cleanup routines:
print( string.format( "%.3f", system.getInfo( "textureMemoryUsed" ) / 1000000 ) .. "MB texture memory allocated" )
I have no problem with removeSelf, Raphael. It’s strange. I’ll try setting nil to all of my objects and see if it solves the problem. If not, I come back here and tell you.
function removeOffscreenItems() for i = 1,#images do local oneImage = images[i] if (oneImage and oneImage.alpha)then if(oneImage.alpha == 0)then oneImage:removeSelf(); oneImage = nil; table.remove( images, i); end end end end
Is there a possibility where that function is not deleting all the images of the table when I tap to exit from a scene? When I choose to close the scene, I remove the enterFrame listener of that function. Maybe it’s not having to delete all the images, do you think the same?
http://www.coronalabs.com/blog/2011/08/15/corona-sdk-memory-leak-prevention-101/#comment-864
Nice post that one!
The problem is almost solved, because I still need to know if the function I posted above is deleting all the images before I change the screen I’m in.
Hi @WilerJr,
Just a note, if your “images” table stores typical images… and I assume it does… you need to loop backwards through it as you clear it out. Why? If you go forward as you typed above, you’ll only clear every other instance out. It works on this logic.
[lua]
–sample table (numbers in place of images, but same idea).
{1,2,3,4,5,6}
–we’ll assume you’re looping from 1 to #images (6).
–iterator “i” is 1… clear that table entry:
{2,3,4,5,6}
–iterator “i” is now 2, clear it… but it hits value “3”, not “2” as you might expect
{2,4,5,6}
–iterator “i” is now 3 (value “5” is cleared)
{2,4,6}
–loop terminates
[/lua]
As you can see, you’re left with half of your images still in there. Bad news if you want to clear all images from a table so Lua can garbage-collect them!
The solution is to just iterate backwards through the loop.
[lua]
for i=#images,1,-1 do
–clear images[i]
end
[/lua]
Hope this helps; it’s a fairly common misunderstanding.
Brent
Wow! Living then learning. It breaks the logic I’ve learned before starting with Corona! haha Thank you once more, Brent.
And tell me one thing: do I have to free local variables before exiting a screen?
My question comes up because even changing the removeOffScreenItems function to your way, nil’ing the objects and removing all runtime and objects listeners, when I go out the screen, the memory usage goes growing every past screen… then I get some lag after a time switching scenes…
Note: before creating a function I call
local functionName = {};
on top of my code and when I’m closing a screen I don’t nil it. Is this wrong?
Hi @WilerJr,
You don’t need to nil out local variables on scene change, assuming you don’t reference them somewhere else (in another containing table), attach a Runtime listener to them, or something else that might be locking them in memory. If you isolate them before leaving the scene, they should be garbage collected properly.
When you exit the scene, you should check that your “images” table has 0 children (just check “#images”).
I’m afraid your memory leak is somewhere else, and finding it could be like finding a needle in a haystack, unfortunately.
Brent
Checking “#images” is not returning a value, Brent… How can I check it?
Tell me a thing, Brent: do all objects inserted on a group be nil’ed if I set nil to this group?
(Editing post) The following code is where I clean my transition, timer and localGroup variables and remove the listeners. This function is called by a “onRelease” inside widget.newButton. Every scene has a function like this.
The function creator creates the images that have to be deleted by removeOffscreenItems function.
function freeEverything() removeOffscreenItemsController = true; if(moveTransition)then transition.cancel(moveTransition); moveTransition = nil; end timer.cancel(counterTimer); counterTimer = nil; Runtime:removeEventListener("enterFrame", removeOffscreenItems); background:addEventListener("touch", creator); Runtime:removeEventListener("enterFrame", rotate); audio.stop(); audio.dispose(song); song = nil; audio.reserveChannels(0); physics.stop(); physics = nil; display.remove(localGroup); localGroup = nil; director:changeScene("main\_page", "overFromLeft"); return true; end
Does count = table.getn( images ) (getn may be deprecated in Lua 5.1+) or count = images.numChildren give you the proper values?
**count = table.getn( images ) **worked. And well… it seems removeOffscreenImages is not removing all the images before closing the screen.
I think I shall create a method to delay a time until that function has cleared all memory. What do you think?
I use a 500ms timer after killing off all my objects and changing scene, seems to be enough for both Simulator and device.
Maybe, almost sure, that is the issue of memory leaking. I’ll try to solve it, using the timer and let a feedback. Thank you, Raphael.
Corona is too fast for itself sometimes, which is normally a good thing. I’ve learned to never switch scenes without a delay of 500-1000ms, as I’ve always experienced some weird crashing due to variables or objects not fully unloading/deleting/disposing.
I"ve realized it. Corona is very fast! OMG! hahaha
I found out it’s not ( REALLY NOT! ) good using **display.remove(object); object = nil; **on the removeOffScreenItems function, because thus the function will not delete the objects; using object:removeSelf() worked perfectly and I took a day to find out it! hahahahah Oh God!
Even with the delay (no matter if I put 5 seconds) before changing screens, the memory usage grows from screen to screen… and I’m removing the listeners, nil’ing my localGroup and the tables…
Hi @WilerJr,
Can you post your “cleanup” function code again? It has likely changed a bit since you posted it above. Maybe we can see something suspicious inside it…
Brent