Detecting a memory leak?

Yes, I removed it from the most recent version. Though, according to the garbagecollect if you do nil out those variables you do eek out a little more memory if for some reason you were really desperate. It saves only a very tiny amount of space though.

I think I worked out a naming function for the objects that the loop produces, but when I send that to the remove function it only removes the first object that hits the bottom of the display.

my code:

[code]
local j = 0
local k = 0
local nameHolder
local nameRemover

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

local x = 50

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

allBall = {}

local function removeByName( allBall, nameRemover )

for i,v in ipairs( allBall ) do

if ( v ~= nil and v == nameRemover ) then

allBall[i] = nil ; break

end

end

end

local function addByName( allBall, nameHolder )

local vCount = 0

for i,v in ipairs( allBall ) do

if ( v == nameHolder ) then

vCount = vCount+1
end

end

if ( vCount == 0 ) then

allBall[#allBall + 1] = nameHolder
end

end

local function randomBall ()

j = j + 1

if x < 3000 then

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

allBall[#allBall + 1] = imageBall
local oneBall = allBall[#allBall]

oneBall.myName = “ball” … j

nameHolder = oneBall.myName

addByName( allBall, nameHolder )

local randomPos = math.random

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

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

oneBall:setLinearVelocity( 0, 600 )

end

local function removeOffscreenItems()

for i = 1, #allBall do

local oneBall = allBall[i]

if ( oneBall.x ) then

if ( oneBall.y > display.contentHeight + 30 ) then

k = k + 1

oneBall.myName = “ball” … k

nameRemover = oneBall.myName

removeByName( allBall, nameRemover )

oneBall:removeSelf()
oneBall = nil

y = y - 1

end

end

end

end

Runtime:addEventListener( “enterFrame”, removeOffscreenItems )

end

y = 11

local timberBall = timer.performWithDelay( x, randomBall, y )
[/code] [import]uid: 10903 topic_id: 3378 reply_id: 11951[/import]

Hi again,
No worries, I don’t mind lending a hand; it seems to be almost working! I think your code is just more complicated than necessary. Around line 56, you have this:

local imageBall = display.newImage( "ball.png" )  
 allBall[#allBall + 1] = imageBall  
 local oneBall = allBall[#allBall]   
 oneBall.myName = "ball" .. j  
 nameHolder = oneBall.myName  
 addByName( allBall, nameHolder )  

You don’t need to do all of this extra assignment stuff. Instead do this:

local imageBall = display.newImage( "ball.png" )  
 addByName( allBall, imageBall )  

Notice I took out four lines, and assigned “imageBall” as the entry that should be added to the table using the addByName function. What happens is, when you create the new display object (the ball), it automatically creates a memory ID for that object, in the form of a long hexidecimal identifier. You just need to pass that ID to the addByName function. The function will ensure that the ID hasn’t been entered multiple times. Later, you can remove it the same way… pass the same ID code to the “removeByName” function, and it’ll be removed.

If you want to skip using my functions entirely, there’s another approach suggested by Ansca. You can loop backwards through a table to delete items, which doesn’t throw the indexing order off. Read this page, and skip down to the “Common Pitfalls” heading for details.

http://developer.anscamobile.com/content/application-programming-guide-graphics-and-drawing#Removing_Objects_Properly

Brent
[import]uid: 9747 topic_id: 3378 reply_id: 11996[/import]

How do I rewrite the remove function then? I assume I have to take out the “for” section. [import]uid: 10903 topic_id: 3378 reply_id: 12005[/import]

Basically, simplify it the same as the add function, as follows (around line 85 in your previous code):

if ( oneBall.x ) then  
 if ( oneBall.y \> display.contentHeight + 30 ) then  
 removeByName( allBall, oneBall )  
 oneBall:removeSelf()  
 oneBall = nil  
  
 y = y - 1  
 end  
end  

“oneBall” is the memory ID that you stored earlier. The remove function should locate it and delete it. But as I mentioned before, it’s worth confirming via a print(#allBall) statement that the item was removed, confirming that the number of table entries drops by 1 every time a ball is removed. [import]uid: 9747 topic_id: 3378 reply_id: 12008[/import]

I’m still only getting the first ball that hits the bottom of the screen removed.

local physics = require("physics")  
physics.start()  
physics.setGravity( 0, 0 )  
  
local x = 50  
  
local background = display.newImage("background.png")  
  
allBall = {}  
  
local function removeByName( allBall, imageBall )  
  
 for i,v in ipairs( allBall ) do  
  
 if ( v ~= nil ) and ( v == imageBall ) then  
  
 allBall[i] = nil ; break   
  
 end  
  
 end  
  
end  
  
local function addByName( allBall, imageBall )  
  
local vCount = 0  
  
for i,v in ipairs( imageBall ) do  
  
 if ( v == imageBall ) then   
  
 vCount = vCount+1   
  
 end  
  
end  
  
 if ( vCount == 0 ) then   
  
 allBall[#allBall + 1] = imageBall  
  
 end  
  
end  
  
local function randomBall ()  
  
if x \< 3000 then  
  
 local imageBall = display.newImage( "ball.png" )  
  
 addByName( allBall, imageBall )  
  
 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 )  
  
end  
  
local function removeOffscreenItems()  
  
 for i = 1, #allBall do  
  
 local imageBall = allBall[i]  
  
 if ( imageBall.x ) then  
  
 if ( imageBall.y \> display.contentHeight + 30 ) then   
   
 removeByName( allBall, imageBall )  
   
 imageBall:removeSelf()  
 imageBall = nil  
  
 end  
  
 end  
  
 end  
  
end  
  
Runtime:addEventListener( "enterFrame", removeOffscreenItems )  
  
end  
  
y = 11  
  
local timberBall = timer.performWithDelay( x, randomBall, y )  
  

On the remove it gets hung up in the section:

  
 if ( v ~= nil ) and ( v == imageBall ) then  
  
 allBall[i] = nil ; break   
  
 end  
  

It enters this if statement, but does not exit. [import]uid: 10903 topic_id: 3378 reply_id: 12021[/import]

Very odd… I see no reason why it shouldn’t be working now. Maybe try removing the “break” command from the loop? That’s the only part I haven’t tested thoroughly in my own game, but according to Lua documentation, it should exit the loop once it finds the desired ID.

Another thought, which would make this whole thing much easier. Why not just create a collision sensor at the bottom of the screen? When the balls hit it, they are removed immediately. This would probably be far more efficient and faster than a Runtime listener constantly monitoring the Y position of each ball. The sensor object (basic rectangle) would be placed off the visual bounds of the screen, but the balls would sense it and be removed…

Brent
[import]uid: 9747 topic_id: 3378 reply_id: 12023[/import]

I added in a collision object and listener, but the same issue still occurs in the same spot. Any thoughts on why that remove function doesn’t work?

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

local score = 0

local x = 50

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

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

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

allBall = {}

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 removeByName( allBall, imageBall )

for i,v in ipairs( allBall ) do

if ( v ~= nil ) and ( v == imageBall ) then

allBall[i] = nil ; break

end

end

end

local function addByName( allBall, imageBall )

local vCount = 0

for i,v in ipairs( imageBall ) do

if ( v == imageBall ) then

vCount = vCount+1

end

end

if ( vCount == 0 ) then

allBall[#allBall + 1] = imageBall

end

end

local function randomBall ()

if x < 3000 then

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

addByName( allBall, imageBall )

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 )

end

local function onCollision( self, event )

if ( event.phase == “began” ) then

for i = 1, #allBall do

local imageBall = allBall[i]

if ( imageBall.x ) then

if ( imageBall.y > 310 ) then

removeByName( allBall, imageBall )

imageBall:removeSelf()
imageBall = nil

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

end

end

end

end

end

bar.collision = onCollision
bar:addEventListener( “collision”, bar )

end

y = 30

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

[/code] [import]uid: 10903 topic_id: 3378 reply_id: 12032[/import]

Oh also it does not work with or without the break. [import]uid: 10903 topic_id: 3378 reply_id: 12033[/import]

I copied your code into a Lua file and tried it; you’re right, it doesn’t work properly. All I can guess is that there’s some confusion happening because of the constant loop (listener) checking and modifying the “allBall” table on the fly. In my own game, the add and remove functions work properly, i.e. when an enemy contained in “enemyTable” dies, I can remove it from the table… the difference being, enemies are not being constantly checked and removed with a RunTime listener; instead, they’re being killed on a per-enemy basis like a collision, when life points drop to zero, etc.

I maintain that a collision sensor is a far superior solution to your program. Why loop over 10, 100, or however many individual balls that are still on the screen? It seems to be a tax on the engine. A collision sensor will handle each ball only when they collide with it, and the other balls (still on the screen) will not be queried for any position check.
[import]uid: 9747 topic_id: 3378 reply_id: 12036[/import]

That simplifies the code a lot, but I’m still leaking memory somewhere.

[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: 3378 reply_id: 12040[/import]

I just remembered reading in a forum post a few weeks ago, some likely bug where if you try to removeSelf() an object with a physical body during the collision handler, it doesn’t get cleared from memory. The workaround was to have the object removal occur on the next game cycle. Another user posted a full sample of that code in the forum thread, explaining how it all works. I think it just requires another function and a true/false flag or something. Sorry I don’t have a link to that thread, but do a search in this “Game edition” forum and all in the “Bug reports” forum… it shouldn’t be more than 10 pages back, since it was posted in the last month.

Best of luck with this… it’s probably getting frustrating, facing a seemingly simple task like this and still getting memory leaks, but I sense it’s getting closer…

[import]uid: 9747 topic_id: 3378 reply_id: 12042[/import]

I don’t think that’s the issue, as the leak still occurs when I put the removal on a timer.

[code]

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

local score = 0

local x = 10

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 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 )

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

local function removeBall ()

imageBall:removeSelf()
imageBall = nil

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

end

local timerRemove = timer.performWithDelay( 400, removeBall, 1 )

end

end

y = 30

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

[/code] [import]uid: 10903 topic_id: 3378 reply_id: 12043[/import]

It’s an issue with the physics bodies. If the bodies are not added then the code doesn’t leak upon removal.

Any thoughts on removing the physics bodies?

[code]

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

local score = 0

local x = 10

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

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

scoreTextfield.text = " " … score

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

local function randomBall ()

if x < 3000 then

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

local randomPos = math.random

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

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

local function removeBall ()

imageBall:removeSelf()
imageBall = nil

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

end

local timerRemove = timer.performWithDelay( 400, removeBall, 1 )

end

end

y = 100

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

[/code] [import]uid: 10903 topic_id: 3378 reply_id: 12044[/import]

I tried your code on my system and I’m getting similar results… physics bodies seem to add to the garbage count, but the garbage count doesn’t return to zero (or the starting value) when they’re all removed.

My suggestion is this: e-mail your code to Carlos (Ansca) directly and ask him about it. Ansca is amazingly responsive to questions, and I’m sure somebody on the staff can answer your question better than I can. It might take a few days, but I’m sure an answer will be provided (and when it does, I’d be curious to hear it, so please forward it along to me, by posting it in this thread where I’ll get update e-mails).

I can’t remember Carlos’ direct e-mail, but “support@anscamobile.com” should reach him eventually.

In the meantime, I’d suggest just moving on to other aspects of the game or Corona or Lua. There is definitely some answer to this issue, but it’s not worth obsessing about (although I admit I’m the obsessive type so I’ve been trying to figure this out, same as you have been).
[import]uid: 9747 topic_id: 3378 reply_id: 12046[/import]

Ignis…
[lua]local dave

function dave()[/lua]

is the correct way to define a local function when you need a forward reference. eg when 2 functions call each other you still need the first one to be able to see the second.

Eg [lua]local second

local function first()
second()
end

function second()
first()
end[/lua]
[import]uid: 6645 topic_id: 3378 reply_id: 12062[/import]

Just wanted to bump this, can any Ansca staff confirm or refute this as a bug? [import]uid: 10903 topic_id: 3378 reply_id: 12521[/import]

I’ve been working on a work around for the issue i was having, but came across another leak issue. Any thoughts would be helpful. Link: http://developer.anscamobile.com/forum/2010/12/30/memory-leak-touch-listener [import]uid: 10903 topic_id: 3378 reply_id: 15282[/import]

Holy cow! Glad I caught this thread. I too am getting garbage that’s not collected when I add physics bodies. When I don’t add them, the garbage count maintains a steady number. When I DO add the physics bodies, the garbage count grows steadily, albeit in small amounts, but it still is a bummer. I’m using the Director class to switch back and forth between screens automatically to automate my testing and my Destroy function. :frowning: [import]uid: 11636 topic_id: 3378 reply_id: 15873[/import]

It’s a confirmed bug, hopefully they’ll fix it in the version coming out soon.

As for now the work around that I’ve used is using transitions to move objects around, and runtime listeners to detect their “collisions.”

Hope that helps. [import]uid: 10903 topic_id: 3378 reply_id: 15888[/import]

Excellent! Well glad it was detected and confirmed. I was going nuts with my memory leak checking and was stoked to pin it down to physicsBodies.

Thanks everyone for getting it narrowed down!

-Mario [import]uid: 11636 topic_id: 3378 reply_id: 15899[/import]