MAV

Blitz3D Forums/Blitz3D Programming/MAV

Whats My Face(Posted 2010) [#1]
Hello I've been working on some code and I noticed that if I run it for roughly 4 hours I get a MAV. I looked at Task Manager and noticed that the mem usage goes up continuously. Could somebody just list a couple common reasons that this happens so I could go looking for them?


SLotman(Posted 2010) [#2]
You are probably creating something over and over and not releasing it :P

If you want a helpful answer, try to replicate the problem with little code as possible, then post it here, or at least give a detailed description of what you're doing, otherwise nobody will be able to help you.

Blitz3D doesn't have any memory leak by itself, so it is probably something you're doing on your code...


Whats My Face(Posted 2010) [#3]
Well if it helps the program MAVs on this line every time.

curline$ = ReadLine(file)



GfK(Posted 2010) [#4]
Well if it helps the program MAVs on this line every time.

curline$ = ReadLine(file)
Maybe you forgot a CloseFile somewhere. You can only have so many files handles open at once.


Whats My Face(Posted 2010) [#5]
OK I've narrowed it down to this large chunk of code (and its not any of the functions in it:

;does drawing, food finding, logic, reproduction, etc
Function UpdateOrganisms()
	For o.organism = Each organism
		;draw the red circle for to visually indicate the organism
		Color 255,0,0
		Oval o\x-(o\mass/2)-camx,o\y-(o\mass/2)-camy,o\mass,o\mass,1 ;draw them
		Color 255,255,255
		
		;life expectancy
		o\lifeExpect = o\lifeExpect - 1
		
		;deal with the carbon
		o\carbon# = o\carbon# - .01 ;suck life away from the organism
		
		;draw information above the organism
		Text o\x-o\mass-camx,o\y-20-camy,"C="+o\carbon 
		Text o\x-o\mass-camx,o\y-30-camy,"ID="+o\ID
		Text o\x-o\mass-camx,o\y-10-camy,"M="+o\mass#
		Text o\x-o\mass-camx,o\y-40-camy,"LE="+o\lifeExpect
		
		;Get the ID of the closest pellet
		Local ID = FindClosestFoodPellet(o\x,o\y,o\range,o\mass,1) 
		Local smallestDist = FindClosestFoodPellet(o\x,o\y,o\range,o\mass,2) 
		
		;find out how far away the nearest food is in words
		Local textdistance$ = "none"
		If smallestDist <> 10001 Then ;remember that 10001 is the default distance if no other food pellets fall within the organisms line of sight
			If smallestDist < (.3)*o\range Then
				textdistance$ = "close"
			ElseIf smallestDist < (.5)*o\range Then
				textdistance$ = "medium"
			ElseIf smallestDist < (1)*o\range Then
				textdistance$ = "far"
			EndIf 
		Else 
			textdistance$ = "none"
		EndIf 
		
		;find the closest other organism
		Local smallestDistToOrg = 10001
		Local orgsize = 0
		Local orgattack = 0
		Local orgdefence = 0
		Local orgradius = 0
		For org.organism = Each organism 
			Local xdist = Abs(o\x-org\x)
			Local ydist = Abs(o\y-org\y)
			Local dist = Sqr((xdist*xdist)+(ydist*ydist))
			If KeyDown(5) Then
				Cls
					Text 0,0,dist 
				Flip
				Delay 500
			EndIf 
			If dist < o\range Then
				If dist < smallestDistToOrg And o\ID <> org\ID Then
					smallestDistToOrg = dist
					orgsize = org\mass
					orgattack = org\attack
					orgdefence = org\defend
					orgradius = org\mass/2
				EndIf 
			EndIf 
		Next
		
		;put the closest organism into perspective
		Local textOrgDist$ = "none"
		Local textSize$ = "none"
		Local textattack$ = "none"
		Local textdefence$ = "none"
		
		;get a text version of how far away the organism is
		If smallestDistToOrg <> 10001 Then
			If smallestDistToOrg <= (o\mass/2)+(orgradius) Then ;if they are touching
				textOrgDist$ = "touching"
			ElseIf smallestDistToOrg < (.3)*o\range Then
				textOrgDist$ = "close"
			ElseIf smallestDistToOrg < (.5)*o\range Then
				textOrgDist$ = "medium"
			ElseIf smallestDistToOrg < (1)*o\range Then
				textOrgDist$ = "far"
			EndIf 
		Else
			textOrgDist$ = "none"
		EndIf 
		
		;now decide how much carbon the cell has
		Local textcarbon$ = "low"
		If o\carbon > o\mass*100
			textcarbon$ = "surplus"
		ElseIf o\carbon > o\mass*30
			textcarbon$ = "high"
		ElseIf o\carbon > o\mass*10
			textcarbon$ = "medium"
		ElseIf o\carbon > o\mass*3
			textcarbon$ = "medium-low"
		Else
			textcarbon$ = "low"
		EndIf 
		
		;open the file so the program can find if there is code for the situation
		Local file = OpenFile(o\code$)
		
		;loop through and see if any lines match the current situation
		Local foundCurSituation = False
		Local curline$
		Local actionToTake
		Repeat
			curline$ = ReadLine(file) ;read a line from the file
			
			;see if this line is the current situation
			If curline$ = ("closestPellet = " + textdistance$ + " + carbonLevel = " + textcarbon$); + " + closestOrgDist = " + textOrgDist$) Then
				foundCurSituation = True
				actionToTake = ReadLine(file)
			EndIf 
		Until Eof(file)
		
		If foundCurSituation = False Then ;for if there isn't something
			WriteLine file,("closestPellet = " + textdistance$ + " + carbonLevel = " + textcarbon$); + " + closestOrgDist = " + textOrgDist$)
			
			If textdistance$ = "none" Then ;because 0 is move towards pellet and there is none to move towards
				actionToTake = Rand(1,4)
			Else
				actionToTake = Rand(0,4)
			EndIf 
			
			WriteLine file,actionToTake
		EndIf 
		
		;close the file because its a good thing to do
		CloseFile(file)
		
		;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
		If KeyHit(57) Then
			actionToTake = 3
		EndIf 
		
		;do the stuff its supposed to
		If actionToTake = 2 Then
			Wander()
		ElseIf actionToTake = 1 Then
			;no code because this is for sitting still
		ElseIf actionToTake = 0 Then ;move towards the closest food pellet
			Local pelletID = FindClosestFoodPellet(o\x,o\y,o\range,o\mass,1) 
			MoveTowards(GetPelletX(pelletID),GetPelletY(pelletID))
		ElseIf actionToTake = 3 Then
			;this section figures out where the old organism is and places a new one right next to it
			Local mult1 = Rnd(0,1)
			Local mult2 = Rnd(0,1)
			If mult1 = 0 Then mult1 = -1
			If mult2 = 0 Then mult2 = -1
			Local newx = o\x + o\mass*mult1
			Local newy = o\y + o\mass*mult2
			
			;figure out how much carbon making the baby is going to cost
			o\carbon = o\carbon - Abs(Float(o\mass*2) - Float(o\attack/10) - Float(o\defend/10) - Float(o\speed/10) - Float(o\range/10))
			
			;create a new organism and take the old one and take half of its energy/carbon away
			CreateGhostOrganism(newx,newy,o\speed+Rnd(-1,1),o\mass+Rnd(-1,1),o\eatEfficancy+Rnd(-1,1),o\attack+Rnd(-1,1),o\defend+Rnd(-1,1),o\carbon/2,o\range+Rnd(-5,5),"organism list\",o\ID)
			o\carbon = o\carbon/2
		ElseIf actionToTake = 4 Then ;reproduce till death
			;figure out how many times org will reproduce
			Local timesToReproduce = o\carbon/10
			
			For n = 1 To timesToReproduce
				mult1 = Rnd(0,1)
				mult2 = Rnd(0,1)
				If mult1 = 0 Then mult1 = -1
				If mult2 = 0 Then mult2 = -1
				newx = o\x + o\mass*mult1
				newy = o\y + o\mass*mult2
			
				;figure out how much carbon making the baby is going to cost
				o\carbon = o\carbon - Abs(Float(o\mass*2) - Float(o\attack/10) - Float(o\defend/10) - Float(o\speed/10) - Float(o\range/100))
				
				If o\carbon < 10 Then 
					Exit
				EndIf
				
				;create a new organism and take the old one and take half of its energy/carbon away
				;CreateGhostOrganism(newx,newy,o\speed+Rnd(-1,1),o\mass+Rnd(-1,1),o\eatEfficancy+Rnd(-1,1),o\attack+Rnd(-1,1),o\defend+Rnd(-1,1),10,o\range(-5,5),"organism list\",o\ID)
				CreateGhostOrganism(newx,newy,o\speed,o\mass,o\eatEfficancy,o\attack,o\defend,10,o\range,"organism list\",o\ID)
			Next
		ElseIf actionToTake = 5 Then ;make litter
			Local littersize = Rnd (2,5)
			
			For n = 1 To littersize
				mult1 = Rnd(0,1)
				mult2 = Rnd(0,1)
				If mult1 = 0 Then mult1 = -1
				If mult2 = 0 Then mult2 = -1
				newx = o\x + o\mass*mult1
				newy = o\y + o\mass*mult2
				
				If o\carbon < 10 Then 
					Exit
				EndIf
				
				;figure out how much carbon making the baby is going to cost
				o\carbon = o\carbon - Abs(Float(o\mass*2) - Float(o\attack/10) - Float(o\defend/10) - Float(o\speed*2) - Float(o\range/100))
				
				;create a new organism and take the old one and take half of its energy/carbon away
				CreateGhostOrganism(newx,newy,o\speed+Rnd(-1,1),o\mass+Rnd(-3,3),o\eatEfficancy,o\attack,o\defend,10,o\range,"organism list\",o\ID)
			Next
		EndIf
			
		;if the organisms carbon runs out kill it
		If o\carbon <= 0 Or o\lifeExpect <= 0 Then
			totalOrgSurvivalTime = (MilliSecs()-begintime) 
			Delete o
		EndIf 
	Next
End Function 



Drak(Posted 2010) [#6]
One thing I noticed:

When your organism dies, you're not freeing it from memory, unless you do it somewhere else.
In the last few lines of your posted code:
;if the organisms carbon runs out kill it
If o\carbon <= 0 Or o\lifeExpect <= 0 Then
     totalOrgSurvivalTime = (MilliSecs()-begintime) 
     Delete o


I don't know what you're using for the actual visible part of your organism, but you'll need to free that from memory. Just add a FreeEntity()

;if the organisms carbon runs out kill it
If o\carbon <= 0 Or o\lifeExpect <= 0 Then
     totalOrgSurvivalTime = (MilliSecs()-begintime) 
     FreeEntity(o\mesh) ;"mesh" being whatever physically\visually represents the organism			
     Delete o


EDIT: Ah, scratch that. I just also noticed you're using just an oval for the actual body, not an entity.


PowerPC603(Posted 2010) [#7]
Readline needs the $ after it:
curline$ = ReadLine(file)

must be:
curline$ = ReadLine$(file)


Otherwise ReadLine(file) "might" return an integer instead of a string.

Don't know if this could be the problem though.


Whats My Face(Posted 2010) [#8]
Thanks for the help PowerPC603 but unfortunately that wasn't it. The program still seems to be skyrocketing up at 100K mem usage every second or so.


Warner(Posted 2010) [#9]
I couldn't find anything in this code that doesn't free. Except maybe the call to 'createGhostOrganism'? Maybe you could temporarily disable this function?
Function CreateGhostOrganism(..)
  Return <----add here
..



D4NM4N(Posted 2010) [#10]
Readline needs the $ after it:
It doesnt actually, you dont need $s or #s at all except on variable declaration, which in b3d is the first time you use it (despite it being better practice to do so).
However you do not need to do this on function calls, only drfinitions. The function will return whatever the function definition specifies.

It -looks- ok scanning over the code, the only thing i can think of after scanning it quickly is; are you -absolutely- sure that -all- the organisms data meet the requirements of the disposal logic?

I notice it is not a complete program so perhaps the leak is somewhere else? I agree with warner, disable the whole func and see what the memory does.


Whats My Face(Posted 2010) [#11]
Its definitely the this code segment:

;open the file so the program can find if there is code for the situation
		Local file = OpenFile(o\code$)
		
		;loop through and see if any lines match the current situation
		Local foundCurSituation = False
		Local curline$
		Local actionToTake
		Repeat
			curline$ = ReadLine$(file) ;read a line from the file
			
			;see if this line is the current situation
			If curline$ = ("closestPellet = " + textdistance$ + " + carbonLevel = " + textcarbon$); + " + closestOrgDist = " + textOrgDist$) Then
				foundCurSituation = True
				actionToTake = ReadLine(file)
			EndIf 
		Until Eof(file)
		
		If foundCurSituation = False Then ;for if there isn't something
			WriteLine file,("closestPellet = " + textdistance$ + " + carbonLevel = " + textcarbon$); + " + closestOrgDist = " + textOrgDist$)
			
			If textdistance$ = "none" Then ;because 0 is move towards pellet and there is none to move towards
				actionToTake = Rand(1,4)
			Else
				actionToTake = Rand(0,4)
			EndIf 
			
			WriteLine file,actionToTake
		EndIf 
		
		;close the file because its a good thing to do
		CloseFile(file)


and has something to do with the way I'm opening and closing the file. I find that even if I get rid of all the file operations and just open and close the file the memory usage still skyrockets.


SLotman(Posted 2010) [#12]
It looks really strange. You Open the file, read it until it ends, then you have "WriteLine". Since you went to the end of file (EOF) this could be the problem. Try closing the file, then re-opening it if you need to write to it.


Whats My Face(Posted 2010) [#13]
I don't think the middle stuff is the problem because when I just open and close the file and comment all the middle code out it still has the problem but when I comment out the opening and closing of the file the memory leak goes away.

Here's everything you'd need to run the file. If you'd like to see the problem for yourself http://www.sendspace.com/file/6osszl


Midimaster(Posted 2010) [#14]
a possible way to get simulate this behavior (shrinking memory) is this:

Repeat
 b=0
 a=OpenFile(b)
 CloseFile a
Until KeyHit(1)


or this:

Repeat
 b$=0
 a=OpenFile(b)
 CloseFile a
Until KeyHit(1)


Can you check if every o\code$ is 100% a string and 100% no number "0"?


Whats My Face(Posted 2010) [#15]
I had the program show the o\code$ and all of them looked right.


Midimaster(Posted 2010) [#16]
sorry for the question: did you check the o\code really exactly in the moment before the line "...OpenFile()"? I would add a..

DEBUGLOG "Now opening: !" + o\code + "!"

...and I would check ASC(Left$(o\code,1)):

DEBUGLOG "Now opening: !" + b + "! !" +ASC(Left(o\code))+"!"

You never know....


Warner(Posted 2010) [#17]
Before opening the file, you should check if it exists:



Axel Wheeler(Posted 2010) [#18]
The MAV itself may be the result of the system running out of memory; thus there may not be an obvious MAV-causing bug in the code itself.

The question is: Why would simply opening and closing a file repeatedly cause mem usage to increase over time? How often is it opening/closing?

Is the OS or virus scanner doing something weird to the file while you're trying to use it?

I agree with Midimaster's logging suggestions (I never knew about the debuglog command myself... thanks!)

Are you running this from within the Blitz IDE? It's errors are sometimes more informative than something like Ideal.


Nate the Great(Posted 2010) [#19]
hmmm odd.... bb might not free it completely... why not just read it once then store it in a string array and then you can simply expand the array.... if you wanna save it, just open the file after the loop ends, then write all the data in the string array over it.


D4NM4N(Posted 2010) [#20]
dbl post


D4NM4N(Posted 2010) [#21]
has something to do with the way I'm opening and closing the file
It could be.. Personally with my file access i use readfile and writefile independently for the higher level read and write they provide, a little more care is needed with openfile.

If you are using openfile things to check are; file exists & you are not over-running (because strings are not a fixed length!)