issue with using removeSelf() from a table of objects

Dear all,

i am facing an issue, i have a table called R2Lobjects and i insert all my enemies in it and when i shoot the enemy in the onCollssion function i do this

[lua]–

if (event.object1.objectType == “food”) then
  event.object1:removeSelf();
  event.object1 = nil
  score = score + 1;
 end

–[/lua]

but when i exit the scene i call on the cleanObject function to clear the memory i always get an error that i am indexing to a nil value but if i did not shoot anything and call this function it works can anyone please help

[lua]–

function clearObjects()

  for i=#R2LObjects,1,-1 do
   local child = table.remove(R2LObjects, i)    – Remove from table
   if child ~= nil then
   print ("object deleted = "… i)
     child:removeSelf()
     child = nil
   end
  end
 R2LObjects = nil
 R2LObjects = {}
 collectgarbage()
 

end

–[/lua]

event.object1 = nil does not make sense to me. i am not sure that you are nil-ing original reference to the object by doing that. you should probably drop that altogether (and accept that memory consumption goes slightly higher and higher until you clean up the scene) OR find a way to access your exact table entry corresponding to the display object and nil that one instead. You could for example, upon creation, say RXLObjects[150].tablePosition = 150 and then use RXLObjects[event.object1.tablePosition] = nil

By doing this you will end up with an array that has holes (i.e. RXLObjects[150] = nil ==> does not exist). So when removing objects at the end just iterate forward using:

for i,v in pairs(RXLObjects) do

v:removeSelf()

end

RXLObjects = nil

That should probably do it but please experiment yourself. Try and display on screen memory and texture memory usage and you can see what difference it makes in terms of memory consumption each approach that you talke. Not nil-ing a “reference” to an object will free up texture but leave a small amount of data in the system (but that is not terrible if clear the scene frequently).

thanks paolo for your reply

well i did the nil part out off having no other solution to try 

i did what you recorded just now still i am getting the same error 

…-sample games\redseashark-v3\redseashark-v1\game.lua:279: attempt to call met

hod ‘removeSelf’ (a nil value)

i dont know why when i remove from the table using remove self my clean up does not work is it the indexing 

and yes i am printing the memory that is why i can see that i still have memory leak 

any help is highly appreciated

thank you  

replace <object>:removeSelf() with display.remove(<object>)

and

for i,v in pairs(RXLObjects) do

print(i…" - ", v)  – Try and take a look at the final configuration of your table and see what you see…

display.remove(v)

end

RXLObjects = nil

i did that now i am getting a new error so is it the way i am using the remove object

MemUsage: 187.0712890625

TexMem:   19.597312

1 -     table: 00D3AF60

2 -     table: 00C7CC10

3 -     table: 00C96E20

4 -     table: 00CDF718

5 -     table: 00D3C910

6 -     table: 00C82140

7 -     table: 00D3F3E8

8 -     table: 00CA1380

9 -     table: 00D472A8

10 -    table: 00D4A1A8

11 -    table: 07D0C040

12 -    table: 07D13090

13 -    table: 07D184B0

Runtime error

ERROR: Attempt to remove an object that’s already been removed from the stage or

 whose parent/ancestor group has already been removed.

stack traceback:

        [C]: ?

        [C]: in function ‘removeSelf’

        ?: in function ‘remove’

        …-sample games\redseas

this is the onCollsion code

if (event.object1.objectType == “food”) then

        

        display.remove(event.object1)

        score = score + 1;

        scoreLabel.text = tostring ( score )

    end

        

    if (event.object2.objectType == “food”) then

        display.remove(event.object2)

        score = score + 1;

        scoreLabel.text = tostring ( score )

    end

you are probably detecting collision event two or three times.  collision event will fire when collision start and when collision ends.  i am not sure if there is also a collision continuing.  you are probably removing the same object two or three times in the collision listener.  you need to filter the event by using event.phase.  see this post (it might be old and referring to slightly outdated APIs but good enough):

http://developer.coronalabs.com/content/game-edition-collision-detection

that is my bet :slight_smile:

man thanks really thanks for the help i tested it just now but still the same thing and same error 

well it seems to me that i could not yet understand when i call removeSelf() or remove() what is the affect on the table for that?

are the indexes changing or something

i tested it if i took the removeSelf() from onCollission() function and run the cleanObject() function it works with no errors and the memory print goes back to 189 with what it started with

solved then?

I haven’t worked with arrays of display objects for a long while but this is what I seem to remember:

table.remove(<table>, <position>) is supposed to re-index keys in an array, while <table>[<position>] = nil is not (it is supposed to leave “holes” in the keys).  It makes a difference when you transverse it (some entries might be nil) and it makes a difference if you are keeping track of specific objects and you need their key never to change.  The best way is always to print out your arrays every time you remove objects, and look at them until you have understood what exactly happens…  and later you can remove print statements.

hi 

well i still did not solve it but i managed to make it simple with your help 

when i do not delete any object it works but when i delete something from the array i get the errors 

[lua]

    eat5 = display.newImage(“media/images/eat01.png”) 

    eat5.x =500; 

    eat5.y =500;

    

tb1 = {eat1,eat2,eat3,eat4,eat5}

–table.remove(tb1,3)

–display.remove(eat3)

print(tb1[1])

print(tb1[2])

print(tb1[3])

print(tb1[4])

print(tb1[5])        

for i=#tb1,1,-1 do

            local child = table.remove(tb1, i)    – Remove from table

            if child ~= nil then

            print ("object deleted = "… i)

                    child:removeSelf()

                    child = nil

            end

end

print (#tb1)

[/lua]

try and invert two lines like this:

display.remove(eat3)

table.remove(tb1,3)

you cannot use reference tb1[3] after it’s been nil-ed in table.remove(…).

event.object1 = nil does not make sense to me. i am not sure that you are nil-ing original reference to the object by doing that. you should probably drop that altogether (and accept that memory consumption goes slightly higher and higher until you clean up the scene) OR find a way to access your exact table entry corresponding to the display object and nil that one instead. You could for example, upon creation, say RXLObjects[150].tablePosition = 150 and then use RXLObjects[event.object1.tablePosition] = nil

By doing this you will end up with an array that has holes (i.e. RXLObjects[150] = nil ==> does not exist). So when removing objects at the end just iterate forward using:

for i,v in pairs(RXLObjects) do

v:removeSelf()

end

RXLObjects = nil

That should probably do it but please experiment yourself. Try and display on screen memory and texture memory usage and you can see what difference it makes in terms of memory consumption each approach that you talke. Not nil-ing a “reference” to an object will free up texture but leave a small amount of data in the system (but that is not terrible if clear the scene frequently).

thanks paolo for your reply

well i did the nil part out off having no other solution to try 

i did what you recorded just now still i am getting the same error 

…-sample games\redseashark-v3\redseashark-v1\game.lua:279: attempt to call met

hod ‘removeSelf’ (a nil value)

i dont know why when i remove from the table using remove self my clean up does not work is it the indexing 

and yes i am printing the memory that is why i can see that i still have memory leak 

any help is highly appreciated

thank you  

replace <object>:removeSelf() with display.remove(<object>)

and

for i,v in pairs(RXLObjects) do

print(i…" - ", v)  – Try and take a look at the final configuration of your table and see what you see…

display.remove(v)

end

RXLObjects = nil

i did that now i am getting a new error so is it the way i am using the remove object

MemUsage: 187.0712890625

TexMem:   19.597312

1 -     table: 00D3AF60

2 -     table: 00C7CC10

3 -     table: 00C96E20

4 -     table: 00CDF718

5 -     table: 00D3C910

6 -     table: 00C82140

7 -     table: 00D3F3E8

8 -     table: 00CA1380

9 -     table: 00D472A8

10 -    table: 00D4A1A8

11 -    table: 07D0C040

12 -    table: 07D13090

13 -    table: 07D184B0

Runtime error

ERROR: Attempt to remove an object that’s already been removed from the stage or

 whose parent/ancestor group has already been removed.

stack traceback:

        [C]: ?

        [C]: in function ‘removeSelf’

        ?: in function ‘remove’

        …-sample games\redseas

this is the onCollsion code

if (event.object1.objectType == “food”) then

        

        display.remove(event.object1)

        score = score + 1;

        scoreLabel.text = tostring ( score )

    end

        

    if (event.object2.objectType == “food”) then

        display.remove(event.object2)

        score = score + 1;

        scoreLabel.text = tostring ( score )

    end

you are probably detecting collision event two or three times.  collision event will fire when collision start and when collision ends.  i am not sure if there is also a collision continuing.  you are probably removing the same object two or three times in the collision listener.  you need to filter the event by using event.phase.  see this post (it might be old and referring to slightly outdated APIs but good enough):

http://developer.coronalabs.com/content/game-edition-collision-detection

that is my bet :slight_smile:

man thanks really thanks for the help i tested it just now but still the same thing and same error 

well it seems to me that i could not yet understand when i call removeSelf() or remove() what is the affect on the table for that?

are the indexes changing or something

i tested it if i took the removeSelf() from onCollission() function and run the cleanObject() function it works with no errors and the memory print goes back to 189 with what it started with

solved then?

I haven’t worked with arrays of display objects for a long while but this is what I seem to remember:

table.remove(<table>, <position>) is supposed to re-index keys in an array, while <table>[<position>] = nil is not (it is supposed to leave “holes” in the keys).  It makes a difference when you transverse it (some entries might be nil) and it makes a difference if you are keeping track of specific objects and you need their key never to change.  The best way is always to print out your arrays every time you remove objects, and look at them until you have understood what exactly happens…  and later you can remove print statements.

hi 

well i still did not solve it but i managed to make it simple with your help 

when i do not delete any object it works but when i delete something from the array i get the errors 

[lua]

    eat5 = display.newImage(“media/images/eat01.png”) 

    eat5.x =500; 

    eat5.y =500;

    

tb1 = {eat1,eat2,eat3,eat4,eat5}

–table.remove(tb1,3)

–display.remove(eat3)

print(tb1[1])

print(tb1[2])

print(tb1[3])

print(tb1[4])

print(tb1[5])        

for i=#tb1,1,-1 do

            local child = table.remove(tb1, i)    – Remove from table

            if child ~= nil then

            print ("object deleted = "… i)

                    child:removeSelf()

                    child = nil

            end

end

print (#tb1)

[/lua]

try and invert two lines like this:

display.remove(eat3)

table.remove(tb1,3)

you cannot use reference tb1[3] after it’s been nil-ed in table.remove(…).