Possible MemoryLeak make games unstable on iOS but not Android?

Hi,

Recently, i’ve been developping a game for both Android and iOs. Our main testing device was my cellphone (a regular semi-intelligent phone, an Lg Optimus L7) and a Acer tablet. But we just buy a Mac and a iTouch 4gen to test our game for iOs, but we’re facing some problem on iOs.

While on Android the games run smoothly and is very fluid and have no particular error, when we test it on iOs, the game simply shut down, for apparently no reason (not true, there must be a reason! :P). Sometime, it shutdown while playing but other time, the games close when we’re simply navigating in the menu.

So, I thought this was maybe because of a memory leaking, but since then, I wasn’t able to find where it could be.

We’re using the Storyboard api, and when we change from scene to scene, we always purge the old scene, and event sometime remove it to save some memory, but that change nothing. (And I don’t use timer or transition)

I try the storyboard.printMemUsage() and that show that we loose some memory from scene to scene, but nothing seem to work when I try to fix it. All display are inserted into the scene group, so when we purge or remove it, everything should be gone right? Do I must do something else to erase everything?

But also, why do everything work on Android but not on iOs? Why it simply shutdown? Every other games runs much more smoothly on my iTouch, so that not because of the system power!

Anyone have some some idea?

Thank you, and have a nice day/night!
P.S. I’m from Québec and speak french, so please forgive me about my bad english! [import]uid: 181680 topic_id: 32793 reply_id: 332793[/import]

I haven’t built my game for iOS yet, just picked up a Mac myself, but something to try would be removing the scene and seeing if that frees the memory. If it doesn’t, there’s a good chance you have a event listener being recreated without being destroyed or something else beyond my knowledge.

There are a few different ways to remove a scene:

Get rid of all scenes that have been created, besides the current one:

storyboard.removeAll()  

If you want to just remove the previous scene, use the following:

storyboard.removeScene( sceneToRemove )  

Using an overlay, call the following in the overlayEnded event for the scene that called the overlay:

local overlay\_scene = event.sceneName  
storyboard.removeScene( overlay\_scene )  

Also, check out this:

local monitorMem = function()  
 collectgarbage()  
 print( "MemUsage: " .. collectgarbage("count") )  
 local textMem = system.getInfo( "textureMemoryUsed" ) / 1000000  
 print( "TexMem: " .. textMem )  
end  
Runtime:addEventListener( "enterFrame", monitorMem )  

I picked it up from another forum post here while doing some debugging. It will help you watch the memory in your app via the console as it’s running in the sim. You may also be able to symbolicate the crash logs from the iPod Touch as well, never tried that with Corona but it’s worth looking into. If that works it might give you some good info. [import]uid: 181948 topic_id: 32793 reply_id: 130389[/import]

I haven’t built my game for iOS yet, just picked up a Mac myself, but something to try would be removing the scene and seeing if that frees the memory. If it doesn’t, there’s a good chance you have a event listener being recreated without being destroyed or something else beyond my knowledge.

There are a few different ways to remove a scene:

Get rid of all scenes that have been created, besides the current one:

storyboard.removeAll()  

If you want to just remove the previous scene, use the following:

storyboard.removeScene( sceneToRemove )  

Using an overlay, call the following in the overlayEnded event for the scene that called the overlay:

local overlay\_scene = event.sceneName  
storyboard.removeScene( overlay\_scene )  

Also, check out this:

local monitorMem = function()  
 collectgarbage()  
 print( "MemUsage: " .. collectgarbage("count") )  
 local textMem = system.getInfo( "textureMemoryUsed" ) / 1000000  
 print( "TexMem: " .. textMem )  
end  
Runtime:addEventListener( "enterFrame", monitorMem )  

I picked it up from another forum post here while doing some debugging. It will help you watch the memory in your app via the console as it’s running in the sim. You may also be able to symbolicate the crash logs from the iPod Touch as well, never tried that with Corona but it’s worth looking into. If that works it might give you some good info. [import]uid: 181948 topic_id: 32793 reply_id: 130389[/import]

Thank for answer, but sadly I already try to remove all the scene, but nothing seem to work…
When I monitor the Memory Usage, I see that i’ve got a memory leak in almost all of my page, but when I look at the code, everything seem to be working.

I also use the xCode console, while testing on device and it write that it crashed because of a memory warning, but my game wasn’t lagging at all!

Here, maybe that gonna more usefull if I show you the code of the 2 first page of my game:

[lua]-----------------------------------------------------------------------------------------

– menu.lua

local storyboard = require( “storyboard” )
local scene = storyboard.newScene()
storyboard.ice = require(“ice”)

– include Corona’s “widget” library
local widget = require “widget”

local function onPlayBtnRelease()

storyboard.purgeScene(“menu”)
storyboard.gotoScene( “carte”, “fade”, 300 )
return true – indicates successful touch
end

local function onPlayBtnRelease02()
storyboard.purgeScene(“menu”)
storyboard.gotoScene( “achievement”, “slideDown”, 300 )

return true
end

local function onPlayBtnRelease03()

storyboard.purgeScene(“menu”)
storyboard.gotoScene( “minigame”, “slideUp”, 300 )

return true
end

local function onPlayBtnRelease04()

storyboard.purgeScene(“menu”)
storyboard.gotoScene( “shop”, “slideDown”, 300 )

return true
end

local function onPlayBtnRelease05()

storyboard.purgeScene(“menu”)
storyboard.gotoScene( “option”, “slideUp”, 300 )

return true
end
– Called when the scene’s view does not exist:
function scene:createScene( event )
local gameData = ice:loadBox( “gameData” )
local group = self.view

audio.setVolume( gameData:retrieve( “volume” ))

local background = display.newImage( “interface/MenuPrincipal_01.png”)
background:setReferencePoint( display.TopLeftReferencePoint )
background.y = display.screenOriginY

local wallet = display.newGroup()
local walletWindow = display.newImage( “interface/porteFeuille.png”)
local walletUsa = display.newText(gameData:retrieve( “moneyUsa” ), 25, 25, native.systemFont, 35)
local walletCan = display.newText(gameData:retrieve( “moneyCan” ), 25, 60, native.systemFont, 35)
local walletEur = display.newText(gameData:retrieve( “moneyEur” ), 25, 95, native.systemFont, 35)
local walletYen = display.newText(gameData:retrieve( “moneyYen” ), 25, 130, native.systemFont, 35)

wallet:insert(walletWindow)
wallet:insert(walletUsa)
wallet:insert(walletCan)
wallet:insert(walletEur)
wallet:insert(walletYen)

wallet.x = display.screenOriginX
wallet.y = display.contentHeight - walletWindow.height

– create a widget button (which will loads level1.lua on release)
playBtn = widget.newButton{
default=“interface/Carte.png”,
over=“interface/Carte.png”,
onRelease = onPlayBtnRelease – event listener function
}
playBtn:setReferencePoint( display.CenterReferencePoint )
playBtn.x = display.contentWidth*0.5
playBtn.y = display.screenOriginY + 340

playBtn02 = widget.newButton{
default=“interface/trophy.png”,
over=“interface/trophy.png”,
onRelease = onPlayBtnRelease02 – event listener function
}
playBtn02:setReferencePoint( display.CenterReferencePoint )
playBtn02.x = 180
playBtn02.y = display.screenOriginY + 320

playBtn03 = widget.newButton{
default=“interface/gameboy.png”,
over=“interface/gameboy.png”,
onRelease = onPlayBtnRelease03 – event listener function
}
playBtn03:setReferencePoint( display.CenterReferencePoint )
playBtn03.x = 300
playBtn03.y = display.screenOriginY + 550
– you must insert .view property for widgets

playBtn04 = widget.newButton{
default=“interface/computer.png”,
over=“interface/computer.png”,
onRelease = onPlayBtnRelease04 – event listener function
}
playBtn04:setReferencePoint( display.CenterReferencePoint )
playBtn04.x = 800
playBtn04.y = display.screenOriginY + 320

playBtn05 = widget.newButton{
default=“interface/option.png”,
over=“interface/option.png”,
onRelease = onPlayBtnRelease05 – event listener function
}
playBtn05:setReferencePoint( display.CenterReferencePoint )
playBtn05.x = 800
playBtn05.y = display.screenOriginY + 600

group:insert( playBtn02 ) – you must insert .view property for widgets
group:insert( background )
group:insert( playBtn )
group:insert( playBtn03 )
group:insert( playBtn04 ) – you must insert .view property for widgets
group:insert( playBtn05 ) – you must insert .view property for widgets
group:insert(wallet)
end

– Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view
–storyboard.printMemUsage()

– INSERT code here (e.g. start timers, load audio, start listeners, etc.)

end

– Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view

– INSERT code here (e.g. stop timers, remove listenets, unload sounds, etc.)

end

– If scene’s view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
local group = self.view
if playBtn then
display.remove( playBtn ) – widgets must be manually removed
playBtn = nil
end

if playBtn02 then
display.remove( playBtn02 ) – widgets must be manually removed
playBtn02 = nil
end

if playBtn03 then
display.remove( playBtn03 ) – widgets must be manually removed
playBtn03 = nil
end

if playBtn04 then
display.remove( playBtn04 ) – widgets must be manually removed
playBtn04 = nil
end

if playBtn05 then
display.remove( playBtn05 ) – widgets must be manually removed
playBtn05 = nil
end
end


– END OF YOUR IMPLEMENTATION

– “createScene” event is dispatched if scene’s view does not exist
scene:addEventListener( “createScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished
scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched whenever before next scene’s transition begins
scene:addEventListener( “exitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be
– automatically unloaded in low memory situations, or explicitly via a call to
– storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( “destroyScene”, scene )


return scene[/lua]

and from this page, I try to go to this page:

[lua]-----------------------------------------------------------------------------------------

– carte.lua

local storyboard = require( “storyboard” )
storyboard.ice = require(“ice”)
local scene = storyboard.newScene()

local widget = require “widget”

local function onPlayBtnRelease()
storyboard.purgeScene( “carte” )
storyboard.gotoScene( “menu”, “slideUp”, 300 )

return true

end

function scene:createScene( event )
local gameData = ice:loadBox( “gameData” ) – this (loading the ice box locally) is what was missing!!
local scoreMontrealTest = gameData:retrieve(“scoreMontreal”)


-------- Récupération des scores --------

local myNumber = 0

-------- Interface --------

local montreal = display.newImage( “interface/place.png”)
montreal.x = 320
montreal.y = 225

local paris = display.newImage( “interface/place.png”)
paris.x = 460
paris.y = 240

local panMontreal = display.newGroup()
local infoMontreal = display.newImage( “interface/panneauMontreal.png”)
local btStartMontreal = display.newImage( “interface/bt_next.png”)
local montrealScore = display.newText(gameData:retrieve( “scoreMontreal” ) or 0, 65, 60, native.systemFont, 25)

panMontreal:insert(infoMontreal)
panMontreal:insert(montrealScore)
panMontreal:insert(btStartMontreal)

btStartMontreal.y = 120
btStartMontreal.x = 75

panMontreal.x = display.viewableContentWidth + -1* display.screenOriginX
panMontreal.y = 140

local panParis = display.newGroup()
local infoParis = display.newImage( “interface/panneauParis.png”)
local btStartParis = display.newImage( “interface/bt_next.png”)

panParis:insert(infoParis)
panParis:insert(btStartParis)

btStartParis.y = 120
btStartParis.x = 75

panParis.x = display.viewableContentWidth + -1* display.screenOriginX
panParis.y = 220

local wallet = display.newGroup()
local walletWindow = display.newImage( “interface/porteFeuille.png”)
local walletUsa = display.newText(gameData:retrieve( “moneyUsa” ), 25, 25, native.systemFont, 35)
local walletCan = display.newText(gameData:retrieve( “moneyCan” ), 25, 60, native.systemFont, 35)
local walletEur = display.newText(gameData:retrieve( “moneyEur” ), 25, 95, native.systemFont, 35)
local walletYen = display.newText(gameData:retrieve( “moneyYen” ), 25, 130, native.systemFont, 35)

wallet:insert(walletWindow)
wallet:insert(walletUsa)
wallet:insert(walletCan)
wallet:insert(walletEur)
wallet:insert(walletYen)

wallet.x = display.screenOriginX
wallet.y = display.contentHeight - walletWindow.height

local group = self.view

– Display a background image
local background = display.newImage( “interface/Carte_01.png”)
background:setReferencePoint( display.TopLeftReferencePoint )
background.y = display.screenOriginY

– Widget Button
playBtn = widget.newButton{
default=“interface/bt_next.png”,
over=“interface/bt_nextOver.png”,
onRelease = onPlayBtnRelease – event listener function
}
playBtn:setReferencePoint( display.CenterReferencePoint )
playBtn.x = display.contentWidth*0.5
playBtn.y = display.contentHeight - 175

– Display objects
group:insert(background)
group:insert(montreal)
group:insert(paris)
group:insert( playBtn )
group:insert( panMontreal )
group:insert( panParis )
group:insert(wallet)

local onMontreal = function( event )
if(panMontreal.x == display.viewableContentWidth + -1* display.screenOriginX) then
transition.to( panMontreal, { time=200, x= panMontreal.x - 142 } )
end

if(panParis.x < display.viewableContentWidth + -1* display.screenOriginX) then
transition.to( panParis, { time=200, x= panParis.x + 142 } )
end
end

local onParis = function( event )
montrealScore.text = gameData:retrieve( “scoreMontreal” )
if(panParis.x == display.viewableContentWidth + -1* display.screenOriginX) then
transition.to( panParis, { time=200, x= panParis.x - 142 } )
end

if(panMontreal.x < display.viewableContentWidth + -1* display.screenOriginX) then
transition.to( panMontreal, { time=200, x= panMontreal.x + 142 } )
end
end

local startMontreal = function( event )
local options =
{
effect = “fade”,
time = 300,
params = { city = “montreal” }
}
storyboard.purgeScene(“carte”)
storyboard.gotoScene( “loading”, options )
end

playBtn02:addEventListener( “touch”, reset )
montreal:addEventListener( “touch”, onMontreal )
paris:addEventListener( “tap”, onParis )
btStartMontreal:addEventListener( “touch”, startMontreal )
end
– Called immediately after scene has moved onscreen:
function scene:enterScene( event )

local group = self.view
–storyboard.printMemUsage()

– INSERT code here (e.g. start timers, load audio, start listeners, etc.)

end

– Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view

– INSERT code here (e.g. stop timers, remove listenets, unload sounds, etc.)

end

– If scene’s view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
local group = self.view
if playBtn then
display.remove( playBtn ) – widgets must be manually removed
playBtn = nil
end
end


– END OF YOUR IMPLEMENTATION

– “createScene” event is dispatched if scene’s view does not exist
scene:addEventListener( “createScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished
scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched whenever before next scene’s transition begins
scene:addEventListener( “exitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be
– automatically unloaded in low memory situations, or explicitly via a call to
– storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( “destroyScene”, scene )


return scene[/lua]

When I print the memory usage, on the page «Menu» I’m at 277.95 of MemUsage and 5.83 of texture memory. When I go to «Carte» it rise to 290.10 and 9.32. And when I go back to menu, it still rise to 303.14 and 10.61, and the number continue to rises as I navigate from page to page…

Any idea anyone? :frowning: [import]uid: 181680 topic_id: 32793 reply_id: 130448[/import]

Thank for answer, but sadly I already try to remove all the scene, but nothing seem to work…
When I monitor the Memory Usage, I see that i’ve got a memory leak in almost all of my page, but when I look at the code, everything seem to be working.

I also use the xCode console, while testing on device and it write that it crashed because of a memory warning, but my game wasn’t lagging at all!

Here, maybe that gonna more usefull if I show you the code of the 2 first page of my game:

[lua]-----------------------------------------------------------------------------------------

– menu.lua

local storyboard = require( “storyboard” )
local scene = storyboard.newScene()
storyboard.ice = require(“ice”)

– include Corona’s “widget” library
local widget = require “widget”

local function onPlayBtnRelease()

storyboard.purgeScene(“menu”)
storyboard.gotoScene( “carte”, “fade”, 300 )
return true – indicates successful touch
end

local function onPlayBtnRelease02()
storyboard.purgeScene(“menu”)
storyboard.gotoScene( “achievement”, “slideDown”, 300 )

return true
end

local function onPlayBtnRelease03()

storyboard.purgeScene(“menu”)
storyboard.gotoScene( “minigame”, “slideUp”, 300 )

return true
end

local function onPlayBtnRelease04()

storyboard.purgeScene(“menu”)
storyboard.gotoScene( “shop”, “slideDown”, 300 )

return true
end

local function onPlayBtnRelease05()

storyboard.purgeScene(“menu”)
storyboard.gotoScene( “option”, “slideUp”, 300 )

return true
end
– Called when the scene’s view does not exist:
function scene:createScene( event )
local gameData = ice:loadBox( “gameData” )
local group = self.view

audio.setVolume( gameData:retrieve( “volume” ))

local background = display.newImage( “interface/MenuPrincipal_01.png”)
background:setReferencePoint( display.TopLeftReferencePoint )
background.y = display.screenOriginY

local wallet = display.newGroup()
local walletWindow = display.newImage( “interface/porteFeuille.png”)
local walletUsa = display.newText(gameData:retrieve( “moneyUsa” ), 25, 25, native.systemFont, 35)
local walletCan = display.newText(gameData:retrieve( “moneyCan” ), 25, 60, native.systemFont, 35)
local walletEur = display.newText(gameData:retrieve( “moneyEur” ), 25, 95, native.systemFont, 35)
local walletYen = display.newText(gameData:retrieve( “moneyYen” ), 25, 130, native.systemFont, 35)

wallet:insert(walletWindow)
wallet:insert(walletUsa)
wallet:insert(walletCan)
wallet:insert(walletEur)
wallet:insert(walletYen)

wallet.x = display.screenOriginX
wallet.y = display.contentHeight - walletWindow.height

– create a widget button (which will loads level1.lua on release)
playBtn = widget.newButton{
default=“interface/Carte.png”,
over=“interface/Carte.png”,
onRelease = onPlayBtnRelease – event listener function
}
playBtn:setReferencePoint( display.CenterReferencePoint )
playBtn.x = display.contentWidth*0.5
playBtn.y = display.screenOriginY + 340

playBtn02 = widget.newButton{
default=“interface/trophy.png”,
over=“interface/trophy.png”,
onRelease = onPlayBtnRelease02 – event listener function
}
playBtn02:setReferencePoint( display.CenterReferencePoint )
playBtn02.x = 180
playBtn02.y = display.screenOriginY + 320

playBtn03 = widget.newButton{
default=“interface/gameboy.png”,
over=“interface/gameboy.png”,
onRelease = onPlayBtnRelease03 – event listener function
}
playBtn03:setReferencePoint( display.CenterReferencePoint )
playBtn03.x = 300
playBtn03.y = display.screenOriginY + 550
– you must insert .view property for widgets

playBtn04 = widget.newButton{
default=“interface/computer.png”,
over=“interface/computer.png”,
onRelease = onPlayBtnRelease04 – event listener function
}
playBtn04:setReferencePoint( display.CenterReferencePoint )
playBtn04.x = 800
playBtn04.y = display.screenOriginY + 320

playBtn05 = widget.newButton{
default=“interface/option.png”,
over=“interface/option.png”,
onRelease = onPlayBtnRelease05 – event listener function
}
playBtn05:setReferencePoint( display.CenterReferencePoint )
playBtn05.x = 800
playBtn05.y = display.screenOriginY + 600

group:insert( playBtn02 ) – you must insert .view property for widgets
group:insert( background )
group:insert( playBtn )
group:insert( playBtn03 )
group:insert( playBtn04 ) – you must insert .view property for widgets
group:insert( playBtn05 ) – you must insert .view property for widgets
group:insert(wallet)
end

– Called immediately after scene has moved onscreen:
function scene:enterScene( event )
local group = self.view
–storyboard.printMemUsage()

– INSERT code here (e.g. start timers, load audio, start listeners, etc.)

end

– Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view

– INSERT code here (e.g. stop timers, remove listenets, unload sounds, etc.)

end

– If scene’s view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
local group = self.view
if playBtn then
display.remove( playBtn ) – widgets must be manually removed
playBtn = nil
end

if playBtn02 then
display.remove( playBtn02 ) – widgets must be manually removed
playBtn02 = nil
end

if playBtn03 then
display.remove( playBtn03 ) – widgets must be manually removed
playBtn03 = nil
end

if playBtn04 then
display.remove( playBtn04 ) – widgets must be manually removed
playBtn04 = nil
end

if playBtn05 then
display.remove( playBtn05 ) – widgets must be manually removed
playBtn05 = nil
end
end


– END OF YOUR IMPLEMENTATION

– “createScene” event is dispatched if scene’s view does not exist
scene:addEventListener( “createScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished
scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched whenever before next scene’s transition begins
scene:addEventListener( “exitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be
– automatically unloaded in low memory situations, or explicitly via a call to
– storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( “destroyScene”, scene )


return scene[/lua]

and from this page, I try to go to this page:

[lua]-----------------------------------------------------------------------------------------

– carte.lua

local storyboard = require( “storyboard” )
storyboard.ice = require(“ice”)
local scene = storyboard.newScene()

local widget = require “widget”

local function onPlayBtnRelease()
storyboard.purgeScene( “carte” )
storyboard.gotoScene( “menu”, “slideUp”, 300 )

return true

end

function scene:createScene( event )
local gameData = ice:loadBox( “gameData” ) – this (loading the ice box locally) is what was missing!!
local scoreMontrealTest = gameData:retrieve(“scoreMontreal”)


-------- Récupération des scores --------

local myNumber = 0

-------- Interface --------

local montreal = display.newImage( “interface/place.png”)
montreal.x = 320
montreal.y = 225

local paris = display.newImage( “interface/place.png”)
paris.x = 460
paris.y = 240

local panMontreal = display.newGroup()
local infoMontreal = display.newImage( “interface/panneauMontreal.png”)
local btStartMontreal = display.newImage( “interface/bt_next.png”)
local montrealScore = display.newText(gameData:retrieve( “scoreMontreal” ) or 0, 65, 60, native.systemFont, 25)

panMontreal:insert(infoMontreal)
panMontreal:insert(montrealScore)
panMontreal:insert(btStartMontreal)

btStartMontreal.y = 120
btStartMontreal.x = 75

panMontreal.x = display.viewableContentWidth + -1* display.screenOriginX
panMontreal.y = 140

local panParis = display.newGroup()
local infoParis = display.newImage( “interface/panneauParis.png”)
local btStartParis = display.newImage( “interface/bt_next.png”)

panParis:insert(infoParis)
panParis:insert(btStartParis)

btStartParis.y = 120
btStartParis.x = 75

panParis.x = display.viewableContentWidth + -1* display.screenOriginX
panParis.y = 220

local wallet = display.newGroup()
local walletWindow = display.newImage( “interface/porteFeuille.png”)
local walletUsa = display.newText(gameData:retrieve( “moneyUsa” ), 25, 25, native.systemFont, 35)
local walletCan = display.newText(gameData:retrieve( “moneyCan” ), 25, 60, native.systemFont, 35)
local walletEur = display.newText(gameData:retrieve( “moneyEur” ), 25, 95, native.systemFont, 35)
local walletYen = display.newText(gameData:retrieve( “moneyYen” ), 25, 130, native.systemFont, 35)

wallet:insert(walletWindow)
wallet:insert(walletUsa)
wallet:insert(walletCan)
wallet:insert(walletEur)
wallet:insert(walletYen)

wallet.x = display.screenOriginX
wallet.y = display.contentHeight - walletWindow.height

local group = self.view

– Display a background image
local background = display.newImage( “interface/Carte_01.png”)
background:setReferencePoint( display.TopLeftReferencePoint )
background.y = display.screenOriginY

– Widget Button
playBtn = widget.newButton{
default=“interface/bt_next.png”,
over=“interface/bt_nextOver.png”,
onRelease = onPlayBtnRelease – event listener function
}
playBtn:setReferencePoint( display.CenterReferencePoint )
playBtn.x = display.contentWidth*0.5
playBtn.y = display.contentHeight - 175

– Display objects
group:insert(background)
group:insert(montreal)
group:insert(paris)
group:insert( playBtn )
group:insert( panMontreal )
group:insert( panParis )
group:insert(wallet)

local onMontreal = function( event )
if(panMontreal.x == display.viewableContentWidth + -1* display.screenOriginX) then
transition.to( panMontreal, { time=200, x= panMontreal.x - 142 } )
end

if(panParis.x < display.viewableContentWidth + -1* display.screenOriginX) then
transition.to( panParis, { time=200, x= panParis.x + 142 } )
end
end

local onParis = function( event )
montrealScore.text = gameData:retrieve( “scoreMontreal” )
if(panParis.x == display.viewableContentWidth + -1* display.screenOriginX) then
transition.to( panParis, { time=200, x= panParis.x - 142 } )
end

if(panMontreal.x < display.viewableContentWidth + -1* display.screenOriginX) then
transition.to( panMontreal, { time=200, x= panMontreal.x + 142 } )
end
end

local startMontreal = function( event )
local options =
{
effect = “fade”,
time = 300,
params = { city = “montreal” }
}
storyboard.purgeScene(“carte”)
storyboard.gotoScene( “loading”, options )
end

playBtn02:addEventListener( “touch”, reset )
montreal:addEventListener( “touch”, onMontreal )
paris:addEventListener( “tap”, onParis )
btStartMontreal:addEventListener( “touch”, startMontreal )
end
– Called immediately after scene has moved onscreen:
function scene:enterScene( event )

local group = self.view
–storyboard.printMemUsage()

– INSERT code here (e.g. start timers, load audio, start listeners, etc.)

end

– Called when scene is about to move offscreen:
function scene:exitScene( event )
local group = self.view

– INSERT code here (e.g. stop timers, remove listenets, unload sounds, etc.)

end

– If scene’s view is removed, scene:destroyScene() will be called just prior to:
function scene:destroyScene( event )
local group = self.view
if playBtn then
display.remove( playBtn ) – widgets must be manually removed
playBtn = nil
end
end


– END OF YOUR IMPLEMENTATION

– “createScene” event is dispatched if scene’s view does not exist
scene:addEventListener( “createScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished
scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched whenever before next scene’s transition begins
scene:addEventListener( “exitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be
– automatically unloaded in low memory situations, or explicitly via a call to
– storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( “destroyScene”, scene )


return scene[/lua]

When I print the memory usage, on the page «Menu» I’m at 277.95 of MemUsage and 5.83 of texture memory. When I go to «Carte» it rise to 290.10 and 9.32. And when I go back to menu, it still rise to 303.14 and 10.61, and the number continue to rises as I navigate from page to page…

Any idea anyone? :frowning: [import]uid: 181680 topic_id: 32793 reply_id: 130448[/import]

A couple of notes on what might be happening:

  1. You aren’t removiing any of the display groups when the scene is destroyed
  2. You call purgeScene on the play button release, but I don’t think that will actually do anything because you are still in the scene that you are trying to purge. I’ve had issues with purging not doing what I want so I always just remove the scene (I don’t have to do any fast switching in my current game, and even with reloading all the graphics I don’t notice any lag).

I would try purging or removing the previous scene in the enterScene event. [import]uid: 181948 topic_id: 32793 reply_id: 130461[/import]

A couple of notes on what might be happening:

  1. You aren’t removiing any of the display groups when the scene is destroyed
  2. You call purgeScene on the play button release, but I don’t think that will actually do anything because you are still in the scene that you are trying to purge. I’ve had issues with purging not doing what I want so I always just remove the scene (I don’t have to do any fast switching in my current game, and even with reloading all the graphics I don’t notice any lag).

I would try purging or removing the previous scene in the enterScene event. [import]uid: 181948 topic_id: 32793 reply_id: 130461[/import]

I’ve noticed some super weird behavior with memory leaks on storyboard transitions myself.

Try doing the following in exitScene:

 local function cleanChildren(group)  
 for i=group.numChildren,1,-1 do  
 if(group[i]) then  
 if(group[i].numChildren) then  
 cleanChildren(group[i])  
 else  
 group[i]:removeSelf()  
 group[i] = nil  
 end  
 end  
 end  
 group:removeSelf()  
 group = nil  
 end  
 cleanChildren(scene.view)  

I’m not sure what ice.lua contains, but also try unrequiring it in exitScene by doing the following:

 package.loaded['ice'] = nil  
 \_G['ice'] = nil  

Good luck, and let me know if this works!

[import]uid: 135827 topic_id: 32793 reply_id: 130510[/import]

Actually, now that I look at your post more closely – I see that you’re leaking regular memory instead of texture memory. I suspect this might be related to the way you’re using the Icebox plugin. 270MB+ of memory usage is crazy (my apps typically use under 3-4MB), so somehow you must be storing a crazy large amount of data and it’s not getting cleared properly.

Ice creates a global variable, so it’s very possible that’s where all your data is leaking into. [import]uid: 135827 topic_id: 32793 reply_id: 130512[/import]

I’ve noticed some super weird behavior with memory leaks on storyboard transitions myself.

Try doing the following in exitScene:

 local function cleanChildren(group)  
 for i=group.numChildren,1,-1 do  
 if(group[i]) then  
 if(group[i].numChildren) then  
 cleanChildren(group[i])  
 else  
 group[i]:removeSelf()  
 group[i] = nil  
 end  
 end  
 end  
 group:removeSelf()  
 group = nil  
 end  
 cleanChildren(scene.view)  

I’m not sure what ice.lua contains, but also try unrequiring it in exitScene by doing the following:

 package.loaded['ice'] = nil  
 \_G['ice'] = nil  

Good luck, and let me know if this works!

[import]uid: 135827 topic_id: 32793 reply_id: 130510[/import]

Actually, now that I look at your post more closely – I see that you’re leaking regular memory instead of texture memory. I suspect this might be related to the way you’re using the Icebox plugin. 270MB+ of memory usage is crazy (my apps typically use under 3-4MB), so somehow you must be storing a crazy large amount of data and it’s not getting cleared properly.

Ice creates a global variable, so it’s very possible that’s where all your data is leaking into. [import]uid: 135827 topic_id: 32793 reply_id: 130512[/import]

Sorry for the delay of my answer, but how could I clear all the data that I stored? Cause I use a global variable that I create in my main (gameData). Before, like my example that I posted, I created the gameData variable only the the create scene of each scene, but that cause MAJOR memory leak. I could reach 700 of memory usage in no time.

And are you sure that I use 270 mb? I wasn’t sure if it was in mb or kb, cause when I use the storyboard.printMemUsage() it said that I use about 0.5 mb sometime…

Here my main.lua :

[lua]display.setStatusBar( display.HiddenStatusBar )

local storyboard = require( “storyboard” )
–storyboard.isDebug = true
storyboard.purgeOnSceneChange = true
storyboard.ice = require(“ice”)
gameData = ice:loadBox( “gameData” )

– EDIT:
– It appears that the storeIfNew must be placed in main.lua
– When I place storeIfNew to add new entry to ice in other module,
– it simply wouldn’t save it.

gameData:storeIfNew( “volume”, 1 )

gameData:storeIfNew( “moneyUsa”, 1000 )
gameData:storeIfNew( “moneyCan”, 0 )
gameData:storeIfNew( “moneyEur”, 0 )
gameData:storeIfNew( “moneyYen”, 0 )

gameData:storeIfNew( “road66”, 0 )
gameData:storeIfNew( “montreal”, 0 )
gameData:storeIfNew( “paris”, 0 )
gameData:storeIfNew( “tokyos”, 0 )

gameData:storeIfNew( “score66”, 0 )
gameData:storeIfNew( “scoreMontreal”, 0 )
gameData:storeIfNew( “scoreParis”, 0 )
gameData:storeIfNew( “scoreTokyo”, 0 )

gameData:storeIfNew( “multiplier”, 0 )

gameData:storeIfNew( “speedLimit”, 0 )
gameData:storeIfNew( “dashLimit”, 0 )
gameData:storeIfNew( “lifeLimit”, 0 )

gameData:storeIfNew( “megaDash”, 0 )
gameData:storeIfNew( “jumpDash”, 0 )

gameData:storeIfNew( “miniGame01”, 0 )
gameData:storeIfNew( “miniGame02”, 0 )

gameData:storeIfNew( “wackScore”, 0 )
gameData:storeIfNew( “fallScore”, 0 )

–Prix des upgrade
–costSpeed_1 = {100,0,0,0}

local costMulti_1 = {200,0,0,0}
local costMulti_2 = {1000,500,0,0}
local costMulti_3 = {1000,500,0,0}
local costMulti_4 = {1000,500,0,0}

local costSpeed_1 = {100, 0,0,0}
local costSpeed_2 = {300, 150,0,0}
local costSpeed_3 = {1000, 500,300,0}
local costSpeed_4 = {5000, 3500,2000,1000}
local costSpeed_5 = {10000, 10000,10000,10000}

local costDash_1 = {150, 0,0,0}
local costDash_2 = {400, 200,0,0}
local costDash_3 = {400, 200,0,0}
local costDash_4 = {400, 200,0,0}

local costLife_1 = {300, 0,0,0}
local costLife_2 = {1000, 500,0,0}
local costLife_3 = {1000, 500,0,0}
local costLife_4 = {1000, 500,0,0}

gameData:storeIfNew( “costMulti1”, costMulti_1)
gameData:storeIfNew( “costMulti2”, costMulti_2)
gameData:storeIfNew( “costMulti3”, costMulti_3)
gameData:storeIfNew( “costMulti4”, costMulti_4)

gameData:storeIfNew( “costSpeed1”, costSpeed_1)
gameData:storeIfNew( “costSpeed2”, costSpeed_2)
gameData:storeIfNew( “costSpeed3”, costSpeed_3)
gameData:storeIfNew( “costSpeed4”, costSpeed_4)
gameData:storeIfNew( “costSpeed5”, costSpeed_5)

gameData:storeIfNew( “costDash1”, costDash_1)
gameData:storeIfNew( “costDash2”, costDash_2)
gameData:storeIfNew( “costDash3”, costDash_3)
gameData:storeIfNew( “costDash4”, costDash_4)

gameData:storeIfNew( “costLife1”, costLife_1)
gameData:storeIfNew( “costLife2”, costLife_2)
gameData:storeIfNew( “costLife3”, costLife_3)
gameData:storeIfNew( “costLife4”, costLife_3)

gameData:save()
– include the Corona “storyboard” module

– load menu screen
storyboard.gotoScene( “menu” )
system.activate( “multitouch”)

local monitorMem = function()
collectgarbage()
print( "MemUsage: " … collectgarbage(“count”) )
local textMem = system.getInfo( “textureMemoryUsed” ) / 1000000
print( "TexMem: " … textMem )
end
Runtime:addEventListener( “enterFrame”, monitorMem )[/lua]

Is there some big problem with it?

And seriously, thank for your answer! [import]uid: 181680 topic_id: 32793 reply_id: 130840[/import]

Sorry for the delay of my answer, but how could I clear all the data that I stored? Cause I use a global variable that I create in my main (gameData). Before, like my example that I posted, I created the gameData variable only the the create scene of each scene, but that cause MAJOR memory leak. I could reach 700 of memory usage in no time.

And are you sure that I use 270 mb? I wasn’t sure if it was in mb or kb, cause when I use the storyboard.printMemUsage() it said that I use about 0.5 mb sometime…

Here my main.lua :

[lua]display.setStatusBar( display.HiddenStatusBar )

local storyboard = require( “storyboard” )
–storyboard.isDebug = true
storyboard.purgeOnSceneChange = true
storyboard.ice = require(“ice”)
gameData = ice:loadBox( “gameData” )

– EDIT:
– It appears that the storeIfNew must be placed in main.lua
– When I place storeIfNew to add new entry to ice in other module,
– it simply wouldn’t save it.

gameData:storeIfNew( “volume”, 1 )

gameData:storeIfNew( “moneyUsa”, 1000 )
gameData:storeIfNew( “moneyCan”, 0 )
gameData:storeIfNew( “moneyEur”, 0 )
gameData:storeIfNew( “moneyYen”, 0 )

gameData:storeIfNew( “road66”, 0 )
gameData:storeIfNew( “montreal”, 0 )
gameData:storeIfNew( “paris”, 0 )
gameData:storeIfNew( “tokyos”, 0 )

gameData:storeIfNew( “score66”, 0 )
gameData:storeIfNew( “scoreMontreal”, 0 )
gameData:storeIfNew( “scoreParis”, 0 )
gameData:storeIfNew( “scoreTokyo”, 0 )

gameData:storeIfNew( “multiplier”, 0 )

gameData:storeIfNew( “speedLimit”, 0 )
gameData:storeIfNew( “dashLimit”, 0 )
gameData:storeIfNew( “lifeLimit”, 0 )

gameData:storeIfNew( “megaDash”, 0 )
gameData:storeIfNew( “jumpDash”, 0 )

gameData:storeIfNew( “miniGame01”, 0 )
gameData:storeIfNew( “miniGame02”, 0 )

gameData:storeIfNew( “wackScore”, 0 )
gameData:storeIfNew( “fallScore”, 0 )

–Prix des upgrade
–costSpeed_1 = {100,0,0,0}

local costMulti_1 = {200,0,0,0}
local costMulti_2 = {1000,500,0,0}
local costMulti_3 = {1000,500,0,0}
local costMulti_4 = {1000,500,0,0}

local costSpeed_1 = {100, 0,0,0}
local costSpeed_2 = {300, 150,0,0}
local costSpeed_3 = {1000, 500,300,0}
local costSpeed_4 = {5000, 3500,2000,1000}
local costSpeed_5 = {10000, 10000,10000,10000}

local costDash_1 = {150, 0,0,0}
local costDash_2 = {400, 200,0,0}
local costDash_3 = {400, 200,0,0}
local costDash_4 = {400, 200,0,0}

local costLife_1 = {300, 0,0,0}
local costLife_2 = {1000, 500,0,0}
local costLife_3 = {1000, 500,0,0}
local costLife_4 = {1000, 500,0,0}

gameData:storeIfNew( “costMulti1”, costMulti_1)
gameData:storeIfNew( “costMulti2”, costMulti_2)
gameData:storeIfNew( “costMulti3”, costMulti_3)
gameData:storeIfNew( “costMulti4”, costMulti_4)

gameData:storeIfNew( “costSpeed1”, costSpeed_1)
gameData:storeIfNew( “costSpeed2”, costSpeed_2)
gameData:storeIfNew( “costSpeed3”, costSpeed_3)
gameData:storeIfNew( “costSpeed4”, costSpeed_4)
gameData:storeIfNew( “costSpeed5”, costSpeed_5)

gameData:storeIfNew( “costDash1”, costDash_1)
gameData:storeIfNew( “costDash2”, costDash_2)
gameData:storeIfNew( “costDash3”, costDash_3)
gameData:storeIfNew( “costDash4”, costDash_4)

gameData:storeIfNew( “costLife1”, costLife_1)
gameData:storeIfNew( “costLife2”, costLife_2)
gameData:storeIfNew( “costLife3”, costLife_3)
gameData:storeIfNew( “costLife4”, costLife_3)

gameData:save()
– include the Corona “storyboard” module

– load menu screen
storyboard.gotoScene( “menu” )
system.activate( “multitouch”)

local monitorMem = function()
collectgarbage()
print( "MemUsage: " … collectgarbage(“count”) )
local textMem = system.getInfo( “textureMemoryUsed” ) / 1000000
print( "TexMem: " … textMem )
end
Runtime:addEventListener( “enterFrame”, monitorMem )[/lua]

Is there some big problem with it?

And seriously, thank for your answer! [import]uid: 181680 topic_id: 32793 reply_id: 130840[/import]