Detecting a memory leak?

Is there any way to detect a memory leak while a game is running? If there’s a horrible leak, I guess it would be apparent after awhile (performance would lag), or maybe the device would eventually throw a “Low Memory” error.

But, is there any method to monitor this during the build stage, to catch potential memory leaks before they get out of control, lost in the code, or duplicated to other places?

Somebody suggested to use this:

print(collectgarbage("count"))

This is fine to get a current “garbage count”, but I don’t see how that can be used to monitor a leak.

Any suggestions for this dilemma?

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

have you tried Instruments? [import]uid: 6459 topic_id: 3378 reply_id: 10047[/import]

Hi Tetu,
I’m not sure what you mean… is Instruments a 3rd-party app or something to test memory usage? I hope that doesn’t sound ignorant, but I’m not certain what you mean by Instruments…
[import]uid: 9747 topic_id: 3378 reply_id: 10060[/import]

Instruments is a program that’s included with xcode [import]uid: 7911 topic_id: 3378 reply_id: 10062[/import]

I am currently preparing the MVC infrastructure for a game that has many stages. So, I am highly exposed to leaking dangers and have invested some time coping with this challenge.

What I am doing (in development stage) is to place a print(Lua Memory) and print(Texture Memory) in EnterFrame. You can also use the “Fps module” that a member has submitted in code section.

The goal is this: Having a dump (empty) scene as the next one for any scene I am working on, when changing to the empty scene both Lua and Texture Memory have to be *instantly* (within a second) zero (or about 100kb for Lua). This means that on every scene transition I have properly cleaned all things (textures, globals, tables, listeners, timers etc) from the outgoing scene and going to the next one without any leaks.

(Of course, you will see the print(Lua) giving a constantly growing number, after starting the empty scene, but this is something normal and will soon get automatically cleaned by GC.)

When finding that these zero figures is not the case and instead the memory increases on each scene transition between a scene and an empty scene, I get notified that something is wrong with my memory management scheme in that scene.

Usually, it is either global variables that don’t get deleted on changeScene, or listeners/timers that don’t get removed. For listeners, I recently built a “registry” for tracking whatever listeners / timers get involved in a scene. The benefit is an automated way to clean listeners on changing scenes. Since listeners get registered on creation they cannot escape from removal when I don’t need them more.
Synopsis: build a memory checking mechanism that reminds you about leaks during the development stage. Don’t let the beast grow. Kill it on its birth day!

[import]uid: 7356 topic_id: 3378 reply_id: 10071[/import]

nice mechanism Magenda!

i found out that even 3 or 4 global variables are enough to cause a memory problem
i check each one of the variables i’m using for being local
with hundreds of lines it’s quite a task, but it is absolutely necessary

and remove listeners too.
however, once i run into a situation where adding and removing an enterFrame listener between scenes was not a good idea, as it messed with the game logic…i couldn’t explain it.
[import]uid: 6459 topic_id: 3378 reply_id: 10072[/import]

Awesome tips Magenda, I will look into these tactics!

And another quick question, which might belong in the Lua Language forum, but since it’s related to memory management…

When declaring unique “children” variables of a local parent variable within a local function, do I also need to somehow declare the child as “local”? See below…

local function spawnEnemy( xPos, yPos )  
 local newEnemy = display.newImageRect( mainGroup, "enemy.png", 40, 40 )  
 newEnemy.x, newEnemy.y = xPos, yPos  
 newEnemy.behavior = "hunt"  
end  

In the function, “newEnemy .behavior” is a child/linked variable of newEnemy (and obviously its a reference created for my program reference, not a built in Corona API handler like .width, .x, .y, etc.). My assumption is that it’s also a local variable, because it’s tied to a local parent declared within a local function. Is this correct? Or, must I write the line as follows?

local newEnemy.behavior = "hunt"

It seems to me that since it’s a child variable of a local parent, it should also be local… I don’t see how a local parent could have a global child, but Lua’s scope method is still not 100% clear to me (getting clearer after 4 weeks, but still not crystal clear). :slight_smile:

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

Keep in mind, that in your example, the Sprite you created isn’t a local object, you only created a local reference to the actual Sprite (which is a display object). The Sprite, however (the thingy you actually see on screen) has been put to the display chain. So when the “newEnemy” pointer to the Sprite is set to nil or when it expired by leaving your function, the Sprite itself will still remain in memory (and on screen) because it still resides in the display chain. Objects can’t be removed from memory as long as they are in the display chain. Display objects must always be removed from the display chain AND all references to them must be set to “nil” to really get rid of them.

And yes, if you have a local table, all of its fields are local, too. If your function expires and you have no other references to that local table (or any stuff within), the complete table should garbage collected (and everythin inside, too).
[import]uid: 9644 topic_id: 3378 reply_id: 10105[/import]

Thanks MauMau, it’s getting clearer now. Just to briefly expand on this issue, if you can please look at the following function…

local function spawnEnemy( xPos, yPos )  
 local newEnemy = display.newImageRect( mainGroup, "enemy.png", 40, 40 )  
 newEnemy.x, newEnemy.y = xPos, yPos  
 newEnemy.stats = { hits=800, attack=100, alignment="evil" }  
end  

In terms of Lua’s internal referencing structure, the references might be something like this:

newEnemy = table: 0x3cd3c0 (or whatever internal reference ID)
newEnemy.stats = table: 0x3bc450 (this is a reference to the “stats” table, a child of newEnemy

So when I delete newEnemy (or rather the reference point to it) all “children” aspects are removed with it also? That includes the table “stats” and any number of other children variables I might have assigned?

As for removing all reference points to newEnemy (when it dies), I am currently deleting or nil’ing the following:

  • newEnemy:removeEventListener( “collision”, newEnemy )
  • newEnemy:removeEventListener( “tap”, selectEnemy )
  • newEnemy:removeSelf() (very important obviously!)
  • all external reference points, i.e. other object variables which reference this enemy’s ID

I am not doing the following via explicit lines of code:

  • removal of the physics body associated with newEnemy (I believe this is removed via the :removeSelf() API)
  • removal of newEnemy from its displayGroup (again, Ansca says this is done along with :removeSelf() )
  • removal of “children” tables like “stats” (as stated, I assume children go bye-bye with their parents)

How does this look to you? Is that thorough enough to ensure total garbage collection? I really appreciate your help on this… my game is currently working very nicely, but before I proceed I’m trying to clean up and check my code carefully to make sure memory is being utilized properly. Your assistance (and everybody’s assistance!) is much appreciated. :slight_smile:

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

@Brent

MauMau gave some excellent tips above and your last statement seems ok to me. I would just add a footnote:

You usually insert a display object to a group. When doing this, you usually, as well, keep a tag for the object as a key value in the group-table after inserting the object e.g. group.myHero=heroDisplayObject . When doing this, just make sure that after group.hero:removeSelf() you also set group.hero=nil to properly delete the object.

You may find helpful this mini-tutorial (especially the last lines) if you don’t feel very confident with groups. [import]uid: 7356 topic_id: 3378 reply_id: 10138[/import]

That’s right, after removing the display object, don’t forget to set it’s “handle” to nil.

Generally, if you nil a table, all it’s children will be removed, too. It’s quite logical: if you don’t have any references to a variable, it becomes obsolete. If you did not create any references to them from anywhere outside, the only way to reference them is by their parent, of course. If the parent is gone, there is no reference left. It’s also important to keep in mind that also listeners are references. Therefore, they should also be detached first before nil’ing a reference -as you did.

Think of it like a chain. If the chain is broken on any place (nil’ed), all stuff below this point becomes obsolete (assuming that there are no additional references).

Imagine what a tremendous amount of work you had to do if you would be forced to set every single variable or table you create to nil again. Instead of doing so, it’s much more efficient and comfortable to keep an eye on your references. If an object has no references to it anymore -it will be trashed. That’s also true for display objects -but being a member of the display chain alone IS a reference, just an internal one. So it needs to be removed from the display chain first to lose this reference.

I am not sure about the proper removal of a display object that has been linked with a physics body. I didn’t work with Corona’s physics yet but I remember that I’ve read a thread here about some kind of bug there (animated sprites aren’t removed from memory when they have been linked to a phyics body).

[import]uid: 9644 topic_id: 3378 reply_id: 10142[/import]

Hi, I’m new to Corona. I’ve been playing around with the multipuck sample code and have developed my own variation on it, but I find that I get a memory leak on the removal. I figure from your comments here that it is because the code isn’t removing from memory the physics body data, but I cannot figure out how to do that.

My code:

[code]
local score = 0

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

main = function()

local x = 500

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

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

scoreTextfield.text = " " … score

local allBall = {}

local function randomBall ()

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

if x < 2000 then

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

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

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

end

local function removeOffscreenItems()

for i = 1, #allBall do

local oneBall = allBall[i]

if ( oneBall.x ) then

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

oneBall:removeSelf()

end

end

end
end

Runtime:addEventListener( “enterFrame”, removeOffscreenItems )

end

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

end

main()
[/code] [import]uid: 10903 topic_id: 3378 reply_id: 11844[/import]

Hi there,

Memory leaks are tricky to find sometimes. I’ve learned that the most important thing, when you remove an object, is removing the object AND every possible reference to that object… then “nil’ing” out that object (object = nil) just to make sure. If there’s any remaining references to an object, i.e. variables that point to it, arrays that contain its ID reference, etc., the object will not become eligible for garbage collection, and thus it will remain in memory.

I haven’t dissected your code entirely, but a few things appear odd to me. I’m not a seasoned expert in Lua, but I think you can do the following:

  1. Remove everything from the core “main()” function… this doesn’t seem necessary to me.

  2. Write a separate “remove” function that handles the object removal… in that function, kill everything: do a removeSelf on the ball and “nil” it out right afterward.

Again, I might be wrong about these things… just keep tinkering around, eventually you’ll locate the leak. Best of luck!

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

if I do this…

local dave

function dave()
end

then do

function main()
dave()
end

Do I think need to do

dave=nil [import]uid: 9371 topic_id: 3378 reply_id: 11895[/import]

Are you trying to declare “dave” as both a local variable and a local function?

If only a function, I prefer this:

local function dave()  
end  

If “dave” is a local variable only (not a function) you shouldn’t name a function the same; worst case, it’ll confuse the system. Best case, it’ll confuse you when you use “dave” later in the code. :slight_smile:

You can “nil” out any local variables if you want… but I don’t think you can (nor need to) “nil” out a local function, unless you are totally done with it and never plan to use it again. A veteran Lua programmer can confirm this… I don’t want to swear on this practice.

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

Brent, thanks for the help.

I took out the main function.

I’ve nil’ed as many of the variables as I can in a remove function. I set the timer repetitions to a variable so I can change that number and see how the leak accumulates. The leak is still happening, and I’m not sure where else it is possibly occurring.

My code mods:

[code]
local score = 0

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

local x = 50

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

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

scoreTextfield.text = " " … score

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

allBall = {}

local function randomBall ()

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

if x < 3000 then

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

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

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 )

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

end

local function removeOffscreenItems()

for i = 1, #allBall do

local oneBall = allBall[i]

if ( oneBall.x ) then

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

oneBall:removeSelf()
oneBall = nil

y = y - 1

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

if y == 0 then
remAll()
end

end

end

end
end

Runtime:addEventListener( “enterFrame”, removeOffscreenItems )

end

y = 20

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

allBall = {}
y = nil
x = nil
allBall = nil
score = nil
collectgarbage(“collect”)
score = "System Memory : " … collectgarbage(“count”)
scoreTextfield.text = " " … score

end

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

Hi again, I think I see the issue… you’re adding new balls to the “allBall” table here:

allBall[#allBall + 1] = imageBall

That’s fine, and it’s useful to have a reference to them. But you have to remove them from the same table when you delete the balls, otherwise the table holds a reference to the ball, and it can’t be garbage collected.

Here, in the delete loop, you’re referencing the ball’s ID within the “allBall” table… again, that’s perfectly fine…

local oneBall = allBall[i]

A few lines later, you’re deleting “oneBall” using removeSelf() and oneBall = nil

What you’re not doing (yet) is removing the ID reference from the “allBall” table! This is a common mistake, and I made it myself once. Adding the following line in your remove function, above the removeSelf() line, would seemingly do the trick (and would if just one ball was being deleted):

allBall[i] = nil

But this too could create a problem! Because you’re looping over a whole table of items, when you remove one index from the table, the whole indexing order shifts around. Let’s say Ball 3 (index #3 in the table) gets deleted, and you do so with the above code line. Now, index #4 becomes index #3! But your looping construct variable (i) is trying to reference #4… and now if Ball 4 (which is now at index #3) is also supposed to be deleted, the loop won’t see it, because the index order has become all muddled.

To solve such things, I create tables with name references. For example:

{ ball1="1", ball2="1", ball3="1" }

“ball1”, “ball2” etc. would actually be memory reference IDs such as “0x19a28b60”, created by the system when the new display object is created (so you don’t need to think about these crazy hex numbers). The value of “1” is irrelevant… the point is, you create a table where the item can be looked up by a name, not by index number. When you loop through it later, you can delete the ID by name, and it won’t matter if the index order goes out of whack.

Here’s the helper function that I wrote to delete by name… place it near the top of your file.

local function removeByName( tableID, name )  
 for i,v in ipairs( tableID ) do  
 if ( v ~= nil and v == name ) then tableID[i] = nil end  
 end  
end  

Call the function as so, during your ball deletion loop:

util\_removeByName( allBall, oneBall )

Hope this works. What I’d do is start with one ball, and add alot of print() statements to check what’s going on. Print the ball’s memory ID when it enters the table (upon creation). Check the number of entries in the table. When it gets deleted, make sure the same ID is being referenced. Then make sure the table count is back to 0, which indicates the index has been effectively deleted. The humble print() statement might be a Lua developer’s best friend. :slight_smile:

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

Almost forgot a very important aspect!

If you (or anybody) intends to use my “removeByName” function, you will also need the “addByName” function. Why? If you’re creating tables with name references, it’s very possible that you’ll end up inserting the same name ID more than once. This might result in something like this:

{ apple="1", orange="1", peach="1", apple="1", apple="1" }

This could be a problem. One might ask “why add them multiple times?” So now I don’t… I use the following function “addByName” to ensure that a name ID only gets added once:

local function addByName( tableID, name )  
 local vCount = 0  
 for i,v in ipairs( tableID ) do  
 if ( v == name ) then vCount = vCount+1 end  
 end  
 if ( vCount == 0 ) then tableID[#tableID+1] = name end  
end  
  
TO USE: addByName( table, item )  

And a slight modification to the remove function… I added a “break” command in the for loop, which should stop the entire routine once the desired item is “found” and deleted. This should save a few milliseconds if you’re looping over a massive table.

local function removeByName( tableID, name )  
 for i,v in ipairs( tableID ) do  
 if ( v ~= nil and v == name ) then tableID[i] = nil ; break end  
 end  
end  
  
TO USE: removeByName( table, item )  

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

You’re a trooper for sticking with this, thanks a million.

For my code, I tried implementing your add and remove functions, and it seems like I’m plugging it in wrong. I assume that the issue I am having is that it’s giving all of the items the same name, and as such is only adding a single item to the table. How do I get it to name each item differently? (If that is the issue at all).

[code]

local score = 0

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

local x = 50

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

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

scoreTextfield.text = " " … score

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

allBall = {}

local function removeByName( allBall, name )

for i,v in ipairs( allBall ) do

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

allBall[i] = nil ; break
end
end
end

local function addByName( allBall, name )

local vCount = 0
for i,v in ipairs( allBall ) do
if ( v == name ) then

vCount = vCount+1
end
end
if ( vCount == 0 ) then

allBall[#allBall + 1] = name
end
end

local function randomBall ()

if x < 3000 then

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

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

addByName( allBall, oneBall )

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

removeByName( allBall, oneBall )

oneBall:removeSelf()
oneBall = nil

y = y - 1

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

end

end

end
end

Runtime:addEventListener( “enterFrame”, removeOffscreenItems )

end

y = 30

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

Isn’t this…

y = nil
x = nil

not needed? [import]uid: 9371 topic_id: 3378 reply_id: 11948[/import]