Memory Leak Issue

I’m try to any number of objects and remove them upon a collision. I find that the remove function isn’t completely clearing the memory causing a memory leak, but I cannot figure out why. Any help is appreciated, thanks in advance.

[code]

local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

local score = 0

local x = 25

local background = display.newImage(“background.png”)

scoreTextfield = display.newText( " " … score, 280, 105, nil, 14 )
scoreTextfield:setTextColor( 0, 0, 0, 255 )

scoreTextfield.text = " " … score

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local bar = display.newImage( “bar.png” )
bar.x = 170 ; bar.y = 350
physics.addBody( bar, “static”, { density=2.9, friction=0.0, bounce = 0 } )

local function randomBall ()

if x < 3000 then

local imageBall = display.newImage( “ball.png” )

local randomPos = math.random

imageBall.x = 10 + randomPos( 300 ); imageBall.y = -20

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( “collision”, imageBall )

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local function onLocalCollision( self, event )

if ( imageBall.x ) then

if ( imageBall.y > 300 ) then

imageBall:removeEventListener( “collision”, imageBall )
imageBall:removeSelf()
imageBall = nil

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

end

end

end

imageBall.collision = onLocalCollision

end

end

y = 30

local timberBall = timer.performWithDelay( x, randomBall, y )

[/code] [import]uid: 10903 topic_id: 3987 reply_id: 303987[/import]

Updated code, but I still get a memory leak.

[code]

local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

local score = 0

local x = 50

scoreTextfield = display.newText( " " … score, 200, 105, nil, 14 )
scoreTextfield:setTextColor( 255, 255, 255, 255 )

scoreTextfield.text = " " … score

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local bar = display.newRect( 0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, “static”, { density=2.9, friction=0.0, bounce = 0 } )

local function onLocalCollision( obj, event )

if ( obj.x ) then

if ( obj.y > 315) then

obj:removeSelf()

end

end

end

local function randomBall ()

if x < 3000 then

local randomPos = math.random

local imageBall = display.newRect( randomPos(300), -20, 30, 30 )
imageBall:setFillColor ( 255, 255, 255 )

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( “collision”, imageBall )

imageBall.collision = onLocalCollision

end

end

y = 14

local timerBall = timer.performWithDelay( x, randomBall, y )

local function memCheck ()

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

end

local timerCheck = timer.performWithDelay( 3000, memCheck, 1 )

[/code] [import]uid: 10903 topic_id: 3987 reply_id: 12279[/import]

I’d firstly verify that the removeSelf() is actually reached.
Put a print there and check if it’s really called as expected. [import]uid: 5750 topic_id: 3987 reply_id: 12293[/import]

Yes it seems to reach the remove.

[code]

local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

local score = 0

local x = 50

scoreTextfield = display.newText( " " … score, 200, 105, nil, 14 )
scoreTextfield:setTextColor( 255, 255, 255, 255 )

scoreTextfield.text = " " … score

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

local bar = display.newRect( 0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, “static”, { density=2.9, friction=0.0, bounce = 0 } )

local function onLocalCollision( obj, event )

if ( obj.x ) then

if ( obj.y > 315) then
print(“removed”)
obj:removeSelf()

end

end

end

local function randomBall ()

if x < 3000 then

local randomPos = math.random

local imageBall = display.newRect( randomPos(300), -20, 30, 30 )
imageBall:setFillColor ( 255, 255, 255 )

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( “collision”, imageBall )

imageBall.collision = onLocalCollision

end

end

y = 14

local timerBall = timer.performWithDelay( x, randomBall, y )

local function memCheck ()

collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

end

local timerCheck = timer.performWithDelay( 3000, memCheck, 1 )

[/code] [import]uid: 10903 topic_id: 3987 reply_id: 12294[/import]

I’m not very into Game Edition, but, don’t you need to remove the body as well ?
You’re currently removing graphics only. [import]uid: 5750 topic_id: 3987 reply_id: 12295[/import]

According to the resources at http://developer.anscamobile.com/content/game-edition-physics-bodies

“A display object that has physical properties can be deleted in the normal way, using object:removeSelf(). It will be automatically removed from both the visible screen and the physical simulation.” [import]uid: 10903 topic_id: 3987 reply_id: 12297[/import]

So, in theory, if you try to remove the body as well, after removing the graphic object, you should get an error saying the phisical object is nil… I’d try that.

You might also want to check in the current bugs. This might be an open one.
[import]uid: 5750 topic_id: 3987 reply_id: 12300[/import]

I think the removeSelf function is supposed to remove the body, their is no physics.removeBody function other than removeSelf as far as I can tell.

I’ll check the bugs. [import]uid: 10903 topic_id: 3987 reply_id: 12301[/import]

As from the Docs, it uses the same method:
http://developer.anscamobile.com/content/game-edition-physics-bodies#Destroying_bodies [import]uid: 5750 topic_id: 3987 reply_id: 12305[/import]

Are you suggesting to use:

if ( obj.y \> 315) then   
 obj.parent:remove( obj )  
 print("removed")   
end  

?

I still get a leak if I do. [import]uid: 10903 topic_id: 3987 reply_id: 12306[/import]

Does it change anything if you nil out the obj ?

[lua]local function onLocalCollision( obj, event )

if ( obj.x ) then

if ( obj.y > 315) then
print(“removed”)
obj:removeSelf()
obj = nil

end

end

end[/lua]

Edit:
Also, check the numChildren in stage… see how it changes…if it grows etc. [import]uid: 5750 topic_id: 3987 reply_id: 12307[/import]

Nil-ing out makes a tiny difference.

The numChildren counts check out fine. [import]uid: 10903 topic_id: 3987 reply_id: 12309[/import]

I gave a better look at your function, my question is, how can you be sure you’re actually leaking memory ?

When your memoryCheck function starts, do you expect all memory to be released ? And if yes, all the 14 balls collided and met the condition within your onLocalCollision function ?

Clearly, if not all the 14 balls collided with such conditions, not all of them are released - and after 3 seconds since start.
[import]uid: 5750 topic_id: 3987 reply_id: 12311[/import]

You can set the memoryCheck to run a number of times and check the value over time. So the last iteration happens well after the last collision.

Then run it again with a larger y value and you’ll find that the last iteration reads a larger memory count.

[code]

local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

local x = 50

collectgarbage(“collect”)
print("System Memory : " … collectgarbage(“count”))

local bar = display.newRect( 0, 350, 350, 20 )
bar:setFillColor ( 255, 255, 255 )
physics.addBody( bar, “static”, { density=2.9, friction=0.0, bounce = 0 } )

local function onLocalCollision( obj, event )

if ( obj.x ) then

if ( obj.y > 315) then
obj:removeSelf()
obj = nil

end

end

end

local function randomBall ()

if x < 3000 then

local randomPos = math.random

local imageBall = display.newRect( randomPos(300), -20, 30, 30 )
imageBall:setFillColor ( 255, 255, 255 )

physics.addBody( imageBall, { density=2.9, friction=0.0, bounce = 0 } )

imageBall:setLinearVelocity( 0, 600 )

imageBall:addEventListener( “collision”, imageBall )

imageBall.collision = onLocalCollision

end

end

y = 10

local timerBall = timer.performWithDelay( x, randomBall, y )

local function memCheck ()

collectgarbage(“collect”)
print("System Memory : " … collectgarbage(“count”))

end

local timerCheck = timer.performWithDelay( 3000, memCheck, 3 ) [import]uid: 10903 topic_id: 3987 reply_id: 12312[/import]

Ok, but I don’t know how much that matters. I was pointing out that you’re not in a “safe” environment in order to call that a memory leak.

If you can’t find this issue among the current bugs, I’d suggest creating a small test-bed with physics, where you know exactly “what and when” once you remove something and exactly what you expect to happen after you check the memory.

For instance, I’d let bodies fall with gravity and once they reached a max Y coord (ground) I’d remove them.
After the simulation terminates I’d check memory and see if anything’s still in memory despite ALL bodies were removed for sure - i.e. if stage.numChildren is the same as before ALL bodies were created.
[import]uid: 5750 topic_id: 3987 reply_id: 12314[/import]

Well what I was doing was using this code to create a tetris like game where the player removes the objects before they hit the bottom of the screen. The loop runs infinitely unless an object hits the bottom at which time the loop ends.

The issue I was getting was that if I run the loop infinitely I get major memory loss on the device after a few hundred objects.

So I devised this code just to test the object removal on event. [import]uid: 10903 topic_id: 3987 reply_id: 12315[/import]

dont know if this is any use but this is what happens to your object during collision (I’m using a print_r function, if you need it i can give you the code)

[lua] ----- beginning of collision - print_r(obj)

table: 0x2c08e50 {
[_proxy] => userdata: 0x2c18cb4
[_functionListeners] => table: 0x2c08e50 {
[collision] => table: 0x2c0d050 {
[1] => function: 0x2663b20
}
}
[_dispatchingEventName] => “collision”
[collision] => function: 0x2663b20
[_class] => table: 0x2c08e50 {
[removeBehavior] => function: 0x264cf00
[initProxy] => function: 0x264cd40
[hasBehavior] => function: 0x264ce80
[addBehavior] => function: 0x264cea0
[__index] => table: 0x264cd20 {
*table: 0x264cd20
}
}
}

----- after obj:removeSelf(), print_r(obj) --------

table: 0x2c08e50 {
[_functionListeners] => table: 0x2c08e50 {
[collision] => table: 0x2c0d050 {
[1] => function: 0x262ac90
}
}
[_dispatchingEventName] => “collision”
}

----- after obj = nil, print_r(obj) ----
nil[/lua]
[import]uid: 6645 topic_id: 3987 reply_id: 12326[/import]

also change your memCheck timer to

[lua]local timerCheck = timer.performWithDelay( 100, memCheck, -1 )[/lua]

eventually it stabilizes to a consistent value, but the more objects you had, the higher this value will be. which to me would confirm a leak i think

with 100 objects

(note the second number is from gcinfo http://lua.gts-stolberg.de/en/Basis.php#gcinfo() )

[lua]startup… System Memory : 68.5634765625 / 68
after collectgarbage before display items added… System Memory : 60.662109375 / 60
after bar & physics added . System Memory : 61.255859375 / 61


System Memory : 60.595703125 / 60
System Memory : 61.126953125 / 61
System Memory : 61.751953125 / 61
System Memory : 62.283203125 / 62
System Memory : 62.736328125 / 62
System Memory : 63.166015625 / 63
System Memory : 63.384765625 / 63
System Memory : 63.603515625 / 63




System Memory : 86.1357421875 / 86
System Memory : 86.3544921875 / 86
System Memory : 85.330078125 / 85
System Memory : 85.017578125 / 85
System Memory : 84.705078125 / 84
System Memory : 84.392578125 / 84
System Memory : 83.7314453125 / 83
System Memory : 83.7080078125 / 83 – ended here…stabilizes
System Memory : 83.7080078125 / 83
System Memory : 83.7080078125 / 83
System Memory : 83.7080078125 / 83
System Memory : 83.7080078125 / 83
System Memory : 83.7080078125 / 83
System Memory : 83.7080078125 / 83[/lua]
[import]uid: 6645 topic_id: 3987 reply_id: 12327[/import]

Can you clarify what your first post means? That’s over my head.

I changed my memcheck function to yours and got similar results so further confirmation of a leak. [import]uid: 10903 topic_id: 3987 reply_id: 12331[/import]

print_r iterates through any object and lists anything it contains. those functions/tables you are seeing are added to the object as part of corona’s internal event management. i wouldnt worry about it, you can see it all disappears when you set your object to nil. but the memory leak youre identifying still seems to exist

it was partly more of a check for ansca to say if there is a memory leak somewhere, maybe it’s because their internal event system etc is still keeping a reference to the object memory (eg in an internal global event table etc) I couldnt say. I dont know how the internals work

j
[import]uid: 6645 topic_id: 3987 reply_id: 12332[/import]