Infinite Timer Leak Memory

No matter what i tried when i use this line always lead to leak 60 KB

obj.TimerInst = timer.performWithDelay(2000, func, 0)

If i remove this timer the leak is gone. on destoryScene event I’m calling timer.cancel(obj.TimerInst) still no hopes.

What i notice is if the timer/transition is in memory and waiting to be trigger in future. and user navigate to other scene even you remove the timer/transition leads to memory leak. But once timer/transition are done. they are removed by themselves which completely removes them memory. But as infinite timer/transition always reside in memory so always leading to leaks.

It’s not a leak the timer needs to hold the function you specifiy on performWithDelay and it will hold it as long as it exists. Even doing cancel will no tlike free the timer. You need to nil your obj.TimerInst also once it is completed or canceled and wait for the garbage collector then it will go away.

Leak is when memory usage grows constantly and never stops (can be with time or with action like screen change).
Memory usage fluctuation (in sane range, what’s more < 1 MB is totaly insignificant) is normal behaviour. You do some action - memory is needed. Garbage will be collected graduadly, not instantly because it would slow app as hell :stuck_out_tongue:

Well whenever the level scene comes in on enterScene I’m using

print(collectgarbage(‘count’) and it seems to be add 60 - 80 KB to previous reading. After playing while failing the level over and over again and starting over again and again it soon becomes 2000 KB from 600 KB, 

I’m also doing collectgarbage() on exitScene event of levelScene. I think really garbage collector doesn’t really collecting that specific memory i tried playing a while but memory keep increasing. 

I think the object on which the transition is called upon is getting removed from destoryScene event of storyboard do i have to do the NIL myself for those objects?

if obj is nilled then timer will be released also but I don’t knwo if the obj is a scene local object or a module local object or something else. I think it comes down to what you do in enter and exit scene and whether you remove the previous scene (which unloads the scene module).

You could try just

timer.performWithDelay(2000, func, 0)

without saving the timer handle and see if that changes things.

Are you nil’ing objects?
Removing objects will only free part of memory reserved for images, but if you keep referencyjny to this objects somewhere then variables still hold some data of object.

In Lua garbagecollector will only kick in if nothing refers variable. So in case:

[code=auto:0]
local a = display.newImage()
local b = a

a:removeSelf() (which happens internally when you exit scene)
a = nil (this also internaly)
[\code]

Then image will be removed but b will still hold some data.
The same principle applies to all object but primitive variables (numbers)

I’m keeping all the reference in scene variable like

local aEnemy = display.newGroup()

aEnemy.EyeL = display.newImage()

aEnemy.EyeR = display.newImage()

scene.Enemies = {}

table.insert(scene.Enemies, aEnemy)

Now i tried self = nil on destoryScene but still keeping it in memory.

on exitScene i’m invidiually calling removeSelf and nil for all elements of aEnemy

Are you saving the timer handle on aEnemy also? Did you try not saving the timer handle? Are you removing the scene before restarting it? Note you can not remove the current scene you have to be on another scene to remove the previous one.

I switched to transition both timer transition have the same problem.

This is how i’m saving the instance on aEnemy

 aEnemy:EvilStart() aEnemy.TransitionInst = transition.to(aEnemy, {time = 1000, onRepeat = function(obj) obj:EvilLoop() end, iterations = 0})

Note aEnemy is a Local variable.

on “exitScene” of LevelScreen i’m calling the following code

 

function aGameScreen:exitScene( event ) for k, vEnemy in pairs(self.EnemyGroup.Enemies) do vEnemy:CancelTimers(); vEnemy = nil end self.EnemyGroup.Enemies = nil end

The cancelTimers event look like below

 function aEnemy:CancelTimers() if (self.TransitionInst ~= nil) then transition.cancel(self.TransitionInst) end transition.cancel() self.Body:removeSelf() self.collisionBox:removeSelf() self.Body = nil self.collisionBox = nil self:removeSelf() self = nil end

I’m using another scene to Reload the game scene

function ReloadScene:enterScene(e) timer.performWithDelay(50, function() Director:CleanUp() -- calls collectgarbarge() Director.GameScreen:ShowLevel(e.params.LevelID) --load the scene again end) end

Ah you are using Director. I do not know how it handles removing scenes. Your cleanup looks good but try to add this

 if (self.TransitionInst ~= nil) then transition.cancel(self.TransitionInst) self.TransitionInst = nil end

Wow this thing is now really freaking me out. i tried what you said. its not that director. its just a Class that calls storyboard 

function aDirector.GameScreen:ShowLevel(pLevelID) local aOptions = { params = { LevelID = pLevelID } }; aDirector.StoryBoard.gotoScene("Scenes.GameScreen", aOptions) end

function aDirector.GameScreen:ReloadLevel(pLevelID) local aOptions = { params = { LevelID = pLevelID } }; aDirector.StoryBoard.gotoScene("Scenes.GameScreenReload", aOptions) end

I think i found the problem. Its not with the main transition.

--PROBLEM IS NOT HERE aEnemy:EvilStart() aEnemy.TransitionInst = transition.to(aEnemy, {time = 1000, onRepeat = function(obj) obj:EvilLoop() end, iterations = 0})

obj:EvilLoop() seems to be causing problem. Below is that function.

 function aEnemy:EvilLoop() local enemy = self; enemy:Bung() enemy = nil end

and Bung looks like the following

function aEnemy:Bung() local BoundInTime = 500 local BoundOutTime = 800 transition.cancel(self.EyeL) transition.cancel(self.EyeR) transition.cancel(self.Mouth) transition.cancel(self.Body) self.EyeL.Trans = transition.to(self.EyeL, {time = BoundInTime, y = self.EyeL.Default.y + 3, transition = easing.outBack, tag = "inGameTrans" }) self.EyeR.Trans = transition.to(self.EyeR, {time = BoundInTime, y = self.EyeR.Default.y + 3, transition = easing.outBack, tag = "inGameTrans" }) self.Mouth.Trans= transition.to(self.Mouth, {time = BoundInTime, y = self.Mouth.Default.y + 3, transition = easing.outBack, tag = "inGameTrans" }) self.Body.Trans = transition.to(self.Body, {time = BoundInTime, height = self.Body.Default.height - 6, y = self.Body.Default.y + 3, transition = easing.outBack, tag = "inGameTrans"}) self.EyeL.Trans = transition.to(self.EyeL, {delay = BoundInTime, time = BoundOutTime, y = self.EyeL.Default.y, transition = easing.outElastic, tag = "inGameTrans" }) self.EyeR.Trans = transition.to(self.EyeR, {delay = BoundInTime, time = BoundOutTime, y = self.EyeR.Default.y, transition = easing.outElastic, tag = "inGameTrans" }) self.Mouth.Trans= transition.to(self.Mouth, {delay = BoundInTime, time = BoundOutTime, y = self.Mouth.Default.y, transition = easing.outElastic, tag = "inGameTrans" }) self.Body.Trans = transition.to(self.Body, {delay = BoundInTime, time = BoundOutTime, height = self.Body.Default.height, y = self.Body.Default.y,transition = easing.outElastic, tag = "inGameTrans" }) end

I modified the removal methods “aEnemy:CancelTimers” like this

 function aEnemy:CancelTimers() if (self.TransitionInst ~= nil) then transition.cancel(self.TransitionInst) self.TransitionInst = nil end if (self.EyeL.Trans ~= nil) then transition.cancel(self.EyeL.Trans) self.EyeL.Trans = nil end if (self.EyeR.Trans ~= nil) then transition.cancel(self.EyeR.Trans) self.EyeR.Trans = nil end if (self.Mouth.Trans ~= nil) then transition.cancel(self.Mouth.Trans) self.Mouth.Trans = nil end if (self.Body.Trans ~= nil) then transition.cancel(self.Body.Trans) self.Body.Trans = nil end transition.cancel() self.Body:removeSelf() self.EyeL:removeSelf() self.EyeR:removeSelf() self.Mouth:removeSelf() self.collisionBox:removeSelf() self.Body = nil self.EyeL = nil self.EyeR = nil self.Mouth = nil self.collisionBox = nil self:removeSelf() self = nil end

Still no hopes :frowning:

If i comment out the transitions in aEnemy:Bung() the leak go away :frowning:

Really stucked!!! Need some help on this one.

Well in bung you are setting two transitions to every object so you are loosing a reference to the BoundIn transitions. This however should not matter as you call transition.cancel() in your CancelTimers so that should cancel all active transitions. You should not have to cancel every transition separately if you do that but you should nil the transition references. I’m not sure what is causing your leak. Use some trial and error.

Seems to be like a Bug in Corona now. the transition which were not completed and scene changed even if you call transition.cancel() won’t clean up those transitions causing leak.

Really awkward thing but still seems to be bug to me. There is something wrong with  transition.pause when i do this those transition are not being removed from memory on scene change. The way i solve it let the in game transition play even if the game is paused.

Well this is the first time you mention pausing the transitions. This is a good question though. Do paused transitions get released when canceling them? Might be a question for the corona staff.

A word of advise to all those who face this problem even after manually cleaning up everything. Don’t leave your transition paused (even you are cleaning them up) they will cause the memory leak. One thing you can do is resume the transition before changing the scene.

https://www.dropbox.com/s/nik0agpq6o7hafz/corona-memory-leak.zip

Yes may be Corona Staff can explain whats going on in this sample. If you uncomment transition.pause(“inGameTransitions”) line from both Scene1.lua and Scene2.lua you will get 10 - 15 KB Leak. if you leave it commented then you will get 5 - 6 KB Leak on scene change.

Even if you leave it commented why there is a leak. Garage collector doesn’t get in i waited a long time.

Wow looks like being Starter means being ignored by Staff. hahahahaha :smiley: