Can't pin down memory leak...desperate for help
BlitzMax Forums/BlitzMax Programming/Can't pin down memory leak...desperate for help
| ||
| Hello folks, I've been pulling my hair out trying to find a memory leak, and I've managed to come reasonably close to isolating it here. Could somebody take pity on me and point out the (most likely obvious) reason the following program leaks memory like a sieve? It has -something- to do with the XML parser and the Clone() method, but I just can't pin down what it is... A massive thanks in advance, Tom
Type Brick
Field name$=""
Field spriteName$=""
Method Clone(brickToCloneFrom:Brick)
name$ = brickToCloneFrom.name$
spritename$ = brickToCloneFrom.spriteName$
End Method
Method LoadFromXML(XMLToLoadFrom$)
SetStringFromXML(name$, XMLToLoadFrom$, "brickName")
SetStringFromXML(spriteName$, XMLToLoadFrom$, "spriteName")
End Method
End Type
Type Game
Field brickTemplates:TList
Field currentBricks:TList
Method Initialize()
brickTemplates = CreateList()
currentBricks = CreateList()
End Method
Method LoadTemplateData()
Local i
Local tmpBrick:Brick
Local tmpXML$
For i = 0 To 10
tmpXML$ = "<brick><brickName>foo" + i + "</brickName><spriteName>bar</spriteName></brick>"
tmpBrick = New Brick
tmpBrick.LoadFromXML(tmpXML$)
ListAddLast(brickTemplates, tmpBrick)
Next
End Method
Method LoadLevelData()
Local i
Local tmpBrick:Brick, brickToClone:Brick
Local tmpXML$
currentBricks = CreateList()
For i = 1 To 100
tmpBrick = New Brick
tmpXML$ = "<brick><brickName>foo" + Rand(0, 10) + "</brickName></brick>"
tmpBrick.LoadFromXML(tmpXML$)
For brickToClone = EachIn brickTemplates
If brickToClone.name$ = tmpBrick.name$ Then
tmpBrick.Clone(brickToClone) ' clone from the template to get brick attributes.
Exit
EndIf
Next
ListAddLast(currentBricks, tmpBrick)
Next
End Method
End Type
Function SetStringFromXML(stringToSet:String Var, XMLToParse:String="", tagToRead:String="")
Local tmpValue:String
tmpValue$ = GetDataFromXML$(XMLToParse$, tagToRead$)
If tmpValue$ <> "" Then
stringToSet$ = tmpValue$
EndIf
End Function
Function GetDataFromXML$(XMLtoParse:String="", tagToRead:String="")
' finds LAST occurance of a given tag, returns the data as a string. Use for filling values, NOT for grabbing trees
' if rootOnly, then disregard nested tags.
' Local tmpTimer:DebugTimer
' tmpTimer = New DebugTimer
' tmpTimer.StartTimer(tagToRead$)
Local frontIndex:Int=0, backIndex:Int=0, dataToReturn:String=""
frontIndex = XMLtoParse$.FindLast("<" + tagToRead$ + ">") + tagToRead$.length + 2
backIndex = XMLtoParse$.FindLast("</" + tagToRead$ + ">")
If (-1 < frontIndex And frontIndex < backIndex And backIndex <= XMLtoParse$.length)
dataToReturn$ = XMLtoParse$[frontIndex..backIndex]
dataToReturn$.Replace("<", "<")
dataToReturn$.Replace(">", ">")
dataToReturn$.Replace("&tab;", "~t")
dataToReturn$.Replace$("&line;", "~n")
Return dataToReturn$
Else
Return Null
EndIf
End Function
' main loop
Local keepPlaying:Int, tmpCount:Int, i:Int
Local currentGame:Game
keepPlaying = 1
tmpCount = 0
currentGame = New Game
Graphics 1024, 768, 32, 0
While keepPlaying = 1
tmpCount = tmpCount + 1
currentGame.Initialize()
currentGame.LoadTemplateData()
currentGame.LoadLevelData()
FlushMem()
Cls
DrawText("Iteration " + tmpCount + "--memory Used: " + MemAlloced() + " bytes", 10, 10)
Flip()
If KeyHit(KEY_ESCAPE) > 0 Then
keepPlaying = 0
EndIf
Wend
|
| ||
Narrowed it down even further: it seems to be this line causing the trouble:dataToReturn$ = XMLtoParse$[frontIndex..backIndex] EDIT: Managed to plug it using Mid(), but I'd really like to know why the sliced string wasn't working... EDIT AGAIN: Wait, no, Mid() doesn't plug it. Still leaking. Damn. |
| ||
| Not sure why it's leaking but.. If you're declaring dataToReturn as a single string, how are you assigning a slice to it? Shouldn't you be using an Index instead? This would pop an error surely? dataToReturn$ = XMLtoParse$[frontIndex..backIndex] Local a:String[5] For Local i:Int = 0 To 4 a[i] = String(i) Next Local s:String = a[1] 'Local s:String = a[1..2] 'or a[1..1], either doesn't work |
| ||
| Tom: You can slice strings as well as arrays; note that XMLtoParse$ is a string, not an array. Check [ BlitzMax Documentation >> Language Reference >> Slices ] for more on this. The leak persists, however, whether I use string slicing or the Mid() function. Arrgh. This is a show-stopper for me (can't load my data files without leaking memory!) |
| ||
I notice that if instead of commenting out...dataToReturn$ = XMLtoParse$[frontIndex..backIndex] ... I comment out the next... Return dataToReturn$ ... it also plugs the leak. Could the problem be with whatever function is dealing with that returned data? Still poking cluelessly... [MORE... ] This may turn out to be useless, and a wander in the wrong direction, but... commenting out the stringToSet$ below, which is where the XMLToParse[] comes from (if I remember rightly), also stops it... Function SetStringFromXML(stringToSet:String Var, XMLToParse:String="", tagToRead:String="") Local tmpValue:String tmpValue$ = GetDataFromXML$(XMLToParse$, tagToRead$) If tmpValue$ <> "" Then ' stringToSet$ = tmpValue$ EndIf End Function ... and moving up to where that's passed from... Method LoadFromXML(XMLToLoadFrom$) ' SetStringFromXML(name$, XMLToLoadFrom$, "brickName") SetStringFromXML(spriteName$, XMLToLoadFrom$, "spriteName") End Method Disabling the above line stops it, while the other line is OK. I'm a bit stuck as to what happens from here... XML and parsing in general drives me nuts... |
| ||
| my bad! |
| ||
| No problem. I think I've found a workaround--instead of returning the result, I'm passing a var parameter instead [EDIT:] No, I haven't. Damn again. |
| ||
| The version posted at the top does not leak for me, did you modify it or maybe my build of BlitzMax fixes it? |
| ||
| skid: ...which build do you have? I just re-copy-and-pasted it and it's failed on me again. I'm running version 1.10, and it's leaking for me on OS X -and- on Windows. My modules are all up to date. |
| ||
| I'm testing on the current inhouse version which will hopefully be ready for release in the next week or two. |
| ||
| Thanks, Skid. I can't tell you how much that puts my mind at ease--it's a lucky thing I got my hair cut short a few days ago, or I'd be missing huge chunks of it right now... Tom /eagerly awaiting that release so I can start using FlushMem() again! |