MAV
Blitz3D Forums/Blitz3D Programming/MAV
| ||
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? |
| ||
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... |
| ||
Well if it helps the program MAVs on this line every time.curline$ = ReadLine(file) |
| ||
Well if it helps the program MAVs on this line every time. Maybe you forgot a CloseFile somewhere. You can only have so many files handles open at once. curline$ = ReadLine(file) |
| ||
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 |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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 .. |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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 |
| ||
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"? |
| ||
I had the program show the o\code$ and all of them looked right. |
| ||
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.... |
| ||
Before opening the file, you should check if it exists: |
| ||
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. |
| ||
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. |
| ||
dbl post |
| ||
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!) |