Freeing Memory?

BlitzMax Forums/BlitzMax Programming/Freeing Memory?

Sean Doherty(Posted 2006) [#1]
I'm looking into a couple of memory issues with my application and I was wondering about GCMemAlloced(). It seems that when GCMemAlloced() is reporting 1,500,000 bytes of memory that my application is very slow. I know I have some memory clean-up issues; but 1,500,000 bytes does seem like enough to cause any issues?

Any insite?


Sean Doherty(Posted 2006) [#2]
Wow, I really had a misconception about how the BlitzMax memory management work. Have a look at he following:

Print "Allocated Memory before call to m_pTGamePlayScreen.Initialize() = " + GCMemAlloced()
m_pTGamePlayScreen = New TGamePlayScreen 
m_pTGamePlayScreen.Initialize()
Print "Allocated Memory after call to m_pTGamePlayScreen.Initialize() = " + GCMemAlloced()        
m_pTGamePlayScreen = Null
m_pTGamePlayScreen = New TGamePlayScreen 
m_pTGamePlayScreen.Initialize()
Print "Allocated Memory after 2nd call to m_pTGamePlayScreen.Initialize() = " +GCMemAlloced() 
GCCollect()                                                                                   
Print "Allocated Memory after call to GCCollect() = " +GCMemAlloced() 


And here is the output:


Allocated Memory before call to m_pTGamePlayScreen.Initialize() = 77149

TGamePlayScreen.Initialize

Allocated Memory after call to m_pTGamePlayScreen.Initialize() = 156311

TGamePlayScreen.Initialize

Allocated Memory after 2nd call to m_pTGamePlayScreen.Initialize() = 232279

Allocated Memory after call to GCCollect() = 229361



I would have though thay setting m_pTGamePlayScreen = Null would have freed the memory?


H&K(Posted 2006) [#3]
Doesnt whether the memory gets freed depend on what the type is.

For example if your type is a pointer to a memory area you have set asside. Then Null dosent free the memory.

I asked a similar question a couple of days ago and was informed that the Gcollection messes up when its deletes Tlists as well (I have never seen this but was told its true)

Post the type


tonyg(Posted 2006) [#4]
I would have though thay setting m_pTGamePlayScreen = Null would have freed the memory?


It does, I think, but only the next time GC is run.
In the following case GC is run at x=42 (for me)...
Type ttest
End Type
Graphics 640,480
For x = 0 To 50
  Cls
  mynew:ttest = New ttest
  DrawText  GCMemAlloced(),0,0
  mynew = Null
  DrawText  GCMemAlloced(),0,20
  DrawText x,0,40
  Flip
  WaitKey()
Next




Sean Doherty(Posted 2006) [#5]
m_pTGamePlayScreen = New TGamePlayScreen

If of type TGamePlayScreen which is a type. Inside the Initialization of TGamePlayScreen a lot of different types are initialized:


Field m_pTTileMapLayer1:LayeredTileMap = Null
Field m_pTTileMapLayer2:LayeredTileMap = Null
Field m_pTTileMapLayer3:LayeredTileMap = Null

Field m_fLevelCompleteFadePercentage:Float
Field m_iState:Int

Field m_fLayer1Alpha:Float = .5
Field m_fLayer2Alpha:Float = 0.55 '.4
Field m_fLayer3Alpha:Float = 0.45 '.3

Field m_iBlend1:Int = 3
Field m_iBlend2:Int = 4
Field m_iBlend3:Int = 4

Field m_iDebug:Int = False

Field m_iLevel:Int = -1
Field m_pTStarship:TStarship = Null
Field m_pTPlayerList:TList = Null
Field m_pTGalaxy:TGalaxy = Null
Field m_pTPlayersAvatar:TStarship = Null
Field m_pTWeaponsMenu:TWeaponsMenu = Null



And they are initialized further in the lower objects. If setting a new'ed object to null doesn't work, how do you free it?

I can free all the lower objects first, but I would be setting them to null to free them?


H&K(Posted 2006) [#6]
I would say (Going only on what Ive been told), is that the M-PtPlayerlist:Tlist might be the problem.

Probably someone who know better should advice you, but the advise given to me was to implicetly free the links in a tlist.

http://www.blitzmax.com/Community/posts.php?topic=59935


tonyg(Posted 2006) [#7]
When you set your TGamePlayScreen to null and remove it from a list (if it's on one) and/or it falls out of scope then the pointer to, for example, m_pTGalaxy:TGalaxy will be deleted. If this is the only reference to that TGalaxy object it will be removed when GC next runs.
However, if it is on a list and you don't remove it from that list you'll still have a reference to it. You'll need to remove it from the list when you delete the object which references it.
Global alllist=CreateList()
Type ttest
  Field t1:ttest1
End Type
Type ttest1
End Type
Graphics 640,480
For x = 0 To 5000
  Cls
  mynew:ttest = New ttest
  mynew.t1:ttest1=New ttest1  
  ListAddLast alllist,mynew.t1
  DrawText  GCMemAlloced(),0,0
'  ListRemove alllist,mynew.t1
  mynew = Null
  DrawText  GCMemAlloced(),0,20
  DrawText x,0,40
  Flip
Next




Sean Doherty(Posted 2006) [#8]
Tony,

m_pTGamePlayScreen is a field of the TReferee object. TReferee exists throughout the life of the game. it is not going to fall out of scope?

Thanks


Sean Doherty(Posted 2006) [#9]
Is there anyway to see everything that is still being allocated. Not the total memory, but the types of objects? Any external programs that do this?


tonyg(Posted 2006) [#10]

m_pTGamePlayScreen is a field of the TReferee object. TReferee exists throughout the life of the game. it is not going to fall out of scope?


OK, so the TReferee object's m-pTGamePlayScreen field (which you have set to null) will no longer reference the
TGamePlayScreen object. If the TGamePlayScreen object is not on a list and nothing else references it, the memory it used will be freed next (or returned to the 'pot') next time GC is run.
As far as I know there is nothing that can list existing objects.
Global alllist=CreateList()
Type treferee
  Field t2:ttest
End Type
Type ttest
  Field t1:ttest1
End Type
Type ttest1
End Type
Graphics 640,480
For x = 0 To 5000
  Cls
  mynew:treferee = New treferee
  mynew.t2:ttest = New ttest
  mynew.t2.t1:ttest1=New ttest1  
  ListAddLast alllist,mynew.t2.t1
  DrawText  GCMemAlloced(),0,0
'  ListRemove alllist,mynew.t1
  mynew.t2 = Null
  DrawText  GCMemAlloced(),0,20
  DrawText x,0,40
  Flip
Next


I might be missing something here but you keep adding to the question. It might be best to post the smallest example which shows the problem.


Sean Doherty(Posted 2006) [#11]
Interesting, I added a bunch of de-allocation code and it help the performance when you start a game over and over. In fact I was able to get the memory reported by GCMemAlloced() up to 3,900,000 bytes without any noticeable performance loss.

However, the memory reported by GCMemAlloced() is still increasing. That kind of makes me think that somehow memory can be lost by GCMemAlloced()?

Anything below you can see that I overlooked:


'Destory the Game Play View Screen
Method Destroy()              
	Local pTPlayer:TPlayer = Null
	     
	Print "TGamePlayScreen.Destroy"
		
	SetImageFont Null  
        
        'Null the Player's Avatar
        m_pTPlayersAvatar.Destroy()
        m_pTPlayersAvatar = Null
        
        'Null the Tile Maps.
	m_pTTileMapLayer1 = Null
	m_pTTileMapLayer2 = Null
	m_pTTileMapLayer3 = Null
		
	'TODO - Need to Implement Destroy for the Tile Maps.
		
	'Destroy the Player's Avatar. 
	m_pTStarship.Destroy() 
	m_pTStarship = Null
		
	'Remove the Players from the List.
	For pTPlayer = EachIn m_pTPlayerList
            
		'Destory the Players.  
		m_pTPlayerList.Remove(pTPlayer)
		pTPlayer.Destroy()
	pTPlayer = Null	
			
	Next 

	'Null the Players List.
	m_pTPlayerList.Clear()
	m_pTPlayerList = Null
	
	'Null the Galaxy.
	m_pTGalaxy.Destroy() 
	m_pTGalaxy = Null
		
	'Null the Weapons Menu.
	If m_pTWeaponsMenu <> Null
		m_pTWeaponsMenu.Destroy()
		m_pTWeaponsMenu = Null
	End If

End Method


Also, does calling GCCollect() in automatic mode do anything?

Thanks


tonyg(Posted 2006) [#12]
Now I really think I have missed something. Is this taken from some commonly available code? If not, then it will be really difficult to find anything wrong with a single method without the rest of the program.
If it's a huge program then you might want to think about writing a debugger module or adding more debug statement. GCCollect will prompt GC to run even in automatic mode...
Global alllist=CreateList()
Type treferee
  Field t2:ttest
End Type
Type ttest
  Field t1:ttest1
End Type
Type ttest1
End Type
Graphics 640,480
For x = 0 To 5000
  Cls
  mynew:treferee = New treferee
  mynew.t2:ttest = New ttest
  mynew.t2.t1:ttest1=New ttest1  
  ListAddLast alllist,mynew.t2.t1
  DrawText  GCMemAlloced(),0,0
  ListRemove alllist,mynew.t2.t1
  mynew.t2 = Null
  DrawText  GCMemAlloced(),0,20
  DrawText x,0,40
  GCCollect()
  Flip
Next



H&K(Posted 2006) [#13]
Are you freeing the tilemaps? (Again this comes down to how you have structured them) If they point to each other (Internsly or externaly) them even tho the mian object goes out of scope, the internal refrences would stop the reference pointer from zeroing.
But Im with Tonyg on this, try to make the smalest code possible that still has the problem.