How are tables cleared the right way?

I wonder if the following construct (example) is getting cleared from memory completely …

local mystuff=display.newGroup() mystuff.sprite=newSprite... mystuff.table={} mystuff.number=123 mystuff.params=newRect... ...

… when doing this:

if mystuff then       display.remove(mystuff)       mystuff=nil end

Is it enough to set mystuff to nil to get the sprites deleted correctly or the rect?

What about the other values, like numbers (or stings)?

from what i understand, lua is very much about tables and its a great strength since it is easy to handle.

all objects with their parameters and what not can be inserted into a display group (table), and when you at some point delete that display group with a simple display.remove(mygroup) then it all goes to the trash bin (garbage handler)

i almost never nil large arrays either since they are always local variables created in a local function, and by leaving the function, they no longer exist, I assume because being dumped to the garbage handler as well.

I don’t know the techno lingo here but have been studying app performance over time and I havent seen any memory leaks yet so I assume this is dealt with and dont worry about it.

EDIT - I know of course that I need to take care of timers, sounds, listeners and the like not attached to objects manually.

2nd EDIT - i know setting variables to nil after removing objects (tables) s good practice, and I try to follow it, but I sometimes forget but again, havent seen any issues yet so not quite sure how important that is.

Yes and No. 

All the fields  you added to mystuff go away as soon as you do this:

display.remove( mystuff ) mystuff = nil

However, the display objects you created and added references to (as fields) were not deleted.
 
If you want the sprite and rect removed too, do this:

if( mystuff ) then    display.remove( mystuff.sprite )    display.remove( mystuff.params ) -- not sure about your name choice, but you set params -- from the output of newRect... implying display.newRect    display.remove( mystuff )    mystuff = nil end

All the other stuff can be ignored and will automatically get collected.

Tip: When asking technical and syntax question, to ensure we understand you and there is NO confusion, please provide complete function calls and all the implied code instead of using ellipses.  

Otherwise, you might think you’re implying one thing and we might think you imply another.

Now, if you had done this:

local group = display.newGroup() -- group.sprite = display.newSprite( group, ... -- I use ellipses here because the only important -- parts are the call to display.newSprite() -- and the fact that group is passed as the first arg. -- The sprite is immediately made a child of group. group.table = {} group.number = 123 group.rect = display.newRect( group, ... -- Same note re: ellipses here.

Then this would suffice:

display.remove(group) -- remove group and children group = nil

Thank you for clarifying this! I had meant the non-group approach and your answer helped a LOT!

One more thing regarding scope:

When creating an object inside a function you have to return it, so you later can remove it.

But I wonder what happens with a function getting an object like this…

local myobject=newSprite(...) local myfunction=function(theobject)      local refobj=theobject      -- code doing stuff to refobj here      -- do I have to set refobj to nil here? end myfunction (myobject)

During runtime, like for example a level in a game is played, for example you want to remove myobject but the function was called before and in this function the reference to myobject with the name refobj was created… does this mean when doing

display.remove(myobject) myobject=nil

is still leaving refobj as a reference and is not clearing the memory accordingly?

Regarding your group sample here:

What about existing references to (for example) the group.rect object? What happens if there are references to this object still existing in the code, like for example:

myrect=group.rect

Would it still be enough to remove the group and set the group to nil? Or is the “missing” line myrect=nil creating a memory leak?

And what about creating an object inside a function and put it into a group there, so it can get removed when the group is getting removed? Does the object be set to nil inside the function? Example:

local myGroup local createobj = function()      local mynewobj=newSprite(myGroup...)      return mynewobj end -- later when removed: display.remove(myGroup) myGroup=nil

Is this enough to completely remove the created object, or is there still the mynewobj reference there?

How can I remove such an object completely without a scene change for example?

refobj would be a direct reference to theobject which is a direct reference to myobject meaning refobj=theobject=myobject

it is still only a single object

removing refobj means removing the reference to myobject

any actions you do to refobj is assigned to myobject but since refobj is a local variable inside a function, it should “get dumped to garbage” once your code exit the function, meaning refobj should cease to exist and therefore there should not be any need to set it to nil.

removing a parent object will remove all children

this is why having a displaygroup object that you insert all relevant children into is so great.

you can build a full page of objects, then manipulate it using the parent displaygroup only.

fade in/out

move

and yes delete

all gone

much of what you ask here is easily tested  :smiley:

i’m sure RG has more on the subject but he probably still asleep  :rolleyes:

@d.mach - You’re making this more complicated that it is.

  1. If there is variable (*anywhere*) that references a display object and you delete that display object, it WILL NOT be garbage collected.

  2. You can delete objects in three ways:

  • Delete them directly with display.remove( obj ) 
  • Delete them directly with obj:removeSelf( ) – I do not use this because it is unsafe.  Just one mistake can bite you.
  • Delete them by deleting the group they are a child of.
  1. Deleting objects does nothing to variables that reference the objects.

  2. When you have fields on a table or object and that object goes out of scope, the fields are cleared.  i.e. If they were referencing an object, that reference is now gone.

  3. You can clear a variable reference (to a table of a object) to fall out of scope immediately by setting the variable that references the table or object to nil.

    local obj1 = display.newCircle( … ) local obj2 = display.newCircle( … ) local t1 = {} obj1.circ = obj2 t1.circ = obj2 – At this point, both obj1 and t1 have fields referencing obj2 display.remove(obj1) display.remove(obj2) – At this point obj1 and obj2 are removed obj1 = nil obj2 = nil – At this point obj1 can be garbage collected but not obj2 t1 = nil – At this point obj1 and obj2 can be garbage collected

Thanks for the detailed info. This is exactly what I was looking for and which was not clear before!

While searching for a system memory leak I found the following problem with my code:

I’m using a global function with a global transitionStash I always clear with a scene change:

transitionStash={} function cancelAllTransitions()     local x          for x=#transitionStash,1,-1 do         transition.cancel( transitionStash[x])         --print ("Transition Nr. ",x," deleted now!")         transitionStash[x]=nil     end     transitionStash = nil     transitionStash = {}     performWithDelay (1,function() collectgarbage("collect") end,1)     return true end

I’m using this for example inside a mainmenu scene, when clicking on a button some transitions will blend in a level selection overview inside the mainmenu. A back-button will then (also with transitions) blend out the level selection and show the original button again.

After clicking the button again the level selection overview is shown again (using transitions) and the back-button will blend the overview out again… and so on.

After doing this for about 20 times, the system memory will increase about 1MB and tests have shown it is the growing transitionStash array.

Now I wonder how I can use a transitionStash AND avoid the growing system memory?

Here is the code (function) which is called when the back-button is used to show the original main buttons again after the level selection buttons where shown:

local showmenuimagesagain = function()             --blending in all the images we need for the main menu:             transitionStash[#transitionStash+1]=transition.to(gfx.titlelogoshadow,{time=250,delay=1,alpha=0.08,tag="newstart",transition=easing.outQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.titlelogo,{time=320,delay=10,alpha=1,tag="newstart",transition=easing.outQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.btn\_newstart,{time=320,delay=50,alpha=1,tag="newstart",transition=easing.outQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.playbtn\_txt,{time=300,delay=40,alpha=1,tag="newstart",transition=easing.outQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.playbtn\_txtshadow,{time=300,delay=30,alpha=0.25,tag="newstart",transition=easing.outQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.btn\_newrate,{time=320,delay=70,alpha=1,tag="newstart",transition=easing.outQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.ratebtn\_txt,{time=300,delay=60,alpha=1,tag="newstart",transition=easing.outQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.ratebtn\_txtshadow,{time=300,delay=51,alpha=0.25,tag="newstart",transition=easing.outQuad})             fc.startinfotextanimation()             transitionStash[#transitionStash+1]=transition.to(gfx.settings,{time=320,delay=80,alpha=1,transition=easing.inQuad,onComplete=function() composer.state.buttonsactive=1;transition.resume("newstart") end})             transitionStash[#transitionStash+1]=transition.to(gfx.btn\_languageselection,{time=300,delay=60,alpha=1,transition=easing.inQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.btn\_difficulty,{time=300,delay=60,alpha=1,transition=easing.inQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.difficultyicon,{time=300,delay=60,alpha=1,transition=easing.inQuad})             transitionStash[#transitionStash+1]=transition.to(gfx.flagimg,{time=300,delay=60,alpha=1,transition=easing.inQuad})              end

Calling cancelAllTransition() at scene change will clear the used memory btw.

from what i understand, lua is very much about tables and its a great strength since it is easy to handle.

all objects with their parameters and what not can be inserted into a display group (table), and when you at some point delete that display group with a simple display.remove(mygroup) then it all goes to the trash bin (garbage handler)

i almost never nil large arrays either since they are always local variables created in a local function, and by leaving the function, they no longer exist, I assume because being dumped to the garbage handler as well.

I don’t know the techno lingo here but have been studying app performance over time and I havent seen any memory leaks yet so I assume this is dealt with and dont worry about it.

EDIT - I know of course that I need to take care of timers, sounds, listeners and the like not attached to objects manually.

2nd EDIT - i know setting variables to nil after removing objects (tables) s good practice, and I try to follow it, but I sometimes forget but again, havent seen any issues yet so not quite sure how important that is.

Yes and No. 

All the fields  you added to mystuff go away as soon as you do this:

display.remove( mystuff ) mystuff = nil

However, the display objects you created and added references to (as fields) were not deleted.
 
If you want the sprite and rect removed too, do this:

if( mystuff ) then    display.remove( mystuff.sprite )    display.remove( mystuff.params ) -- not sure about your name choice, but you set params -- from the output of newRect... implying display.newRect    display.remove( mystuff )    mystuff = nil end

All the other stuff can be ignored and will automatically get collected.

Tip: When asking technical and syntax question, to ensure we understand you and there is NO confusion, please provide complete function calls and all the implied code instead of using ellipses.  

Otherwise, you might think you’re implying one thing and we might think you imply another.

Now, if you had done this:

local group = display.newGroup() -- group.sprite = display.newSprite( group, ... -- I use ellipses here because the only important -- parts are the call to display.newSprite() -- and the fact that group is passed as the first arg. -- The sprite is immediately made a child of group. group.table = {} group.number = 123 group.rect = display.newRect( group, ... -- Same note re: ellipses here.

Then this would suffice:

display.remove(group) -- remove group and children group = nil

Thank you for clarifying this! I had meant the non-group approach and your answer helped a LOT!

One more thing regarding scope:

When creating an object inside a function you have to return it, so you later can remove it.

But I wonder what happens with a function getting an object like this…

local myobject=newSprite(...) local myfunction=function(theobject)      local refobj=theobject      -- code doing stuff to refobj here      -- do I have to set refobj to nil here? end myfunction (myobject)

During runtime, like for example a level in a game is played, for example you want to remove myobject but the function was called before and in this function the reference to myobject with the name refobj was created… does this mean when doing

display.remove(myobject) myobject=nil

is still leaving refobj as a reference and is not clearing the memory accordingly?

Regarding your group sample here:

What about existing references to (for example) the group.rect object? What happens if there are references to this object still existing in the code, like for example:

myrect=group.rect

Would it still be enough to remove the group and set the group to nil? Or is the “missing” line myrect=nil creating a memory leak?

And what about creating an object inside a function and put it into a group there, so it can get removed when the group is getting removed? Does the object be set to nil inside the function? Example:

local myGroup local createobj = function()      local mynewobj=newSprite(myGroup...)      return mynewobj end -- later when removed: display.remove(myGroup) myGroup=nil

Is this enough to completely remove the created object, or is there still the mynewobj reference there?

How can I remove such an object completely without a scene change for example?

refobj would be a direct reference to theobject which is a direct reference to myobject meaning refobj=theobject=myobject

it is still only a single object

removing refobj means removing the reference to myobject

any actions you do to refobj is assigned to myobject but since refobj is a local variable inside a function, it should “get dumped to garbage” once your code exit the function, meaning refobj should cease to exist and therefore there should not be any need to set it to nil.

removing a parent object will remove all children

this is why having a displaygroup object that you insert all relevant children into is so great.

you can build a full page of objects, then manipulate it using the parent displaygroup only.

fade in/out

move

and yes delete

all gone

much of what you ask here is easily tested  :smiley:

i’m sure RG has more on the subject but he probably still asleep  :rolleyes: