Memory Leak!!!!!
BlitzMax Forums/BlitzMax Programming/Memory Leak!!!!!
| ||
Hey everyone! I meant to have a new version of Ping Pong Battle uploaded today, but alas found a memory leak while play testing. I can't post any code, since I have no clue where it might be coming from, but some general suggestions as to what might be causing it, and how I might fix it or test to see what's causing it would be invaluable. I'm using BlitzMax version 1.34, and here's what happened. I was playtesting the game on my Win7 laptop, it was running very nicely without any glitches. Played for about 20 minutes, and then got a Windows7 error pop-up that 'This program needs to close' with no explanation of why. So I closed it, tried to recompile my code so I could hunt around for this glitch and got a failed to compile error that said I had 'No Memory'. After waiting around for a few minutes, I could compile just fine, but I fear there is a memory leak that caused my program to soak up ALL available RAM until it crashed :) Your help with this, would be most appreciated. |
| ||
I haven't experienced any memory leaks myself, but here's a possible way to find out where the leak is! :)Local MA:Int = GCMemAlloced() 'The function or code you want to test for leakage here Print GCMemAlloced() - MA |
| ||
you might be dividing by zero, make sure you are not first, |
| ||
Ok, I'll try out your code ;) Thareh! That should help out. @Slenkar I don't 'think' that I'm dividing by zero, but I'll go through my code to make sure ;) |
| ||
See if it gobbles up tons of memory in the task manager. |
| ||
Any reason that you're still on 1.34? The latest version is 1.39, and there have been quite a few bugfixes since 1.34... |
| ||
Compile in multithreaded mode. If the leak is fixed, you probably have a circular reference not getting collected in single-threaded mode. |
| ||
JoshK is one of the easiest ways to ensure it is not a circular reference bug. |
| ||
Oky doke, there is a DEFINITE memory leak. Had task manager running while playing the game, and every time it hit a new major function such as the main loop, game over, character select, or title screen, the free physical memory dropped by about 50 to 100MB. It would then stabilize, once in the function, and remain stable throughout. But it never really recovers any free memory, and eventually runs out and crashes ;) So I'm betting I'm doing something dumb. For a lot of my functions, I load images as local variables so I don't have to as global ones(To cut down on initial load time). should I free those before moving on to a new function, and should I free any local variables as well? (And if so, how do I do so?) Also is there anyway to ADD to the free physical memory? Thanks! I'll try the multithreaded build now JoshK :) |
| ||
Well multithreaded build didn't work. I'm still losing massive chunks of memory :( |
| ||
Also is there anyway to ADD to the free physical memory? Put in some new RAM sticks ? :-) |
| ||
lol |
| ||
How do you, replenish the free physical memory? It slowly drops with every new function I enter, and even if I set all the local variables to NULL at the end of the function, it still doesn't relinquish any of the memory it took, even though those variables don't seem to be in use anymore. Thats what I really need it to do, so that I have x amount of memory to work with in each function, and then can free it when I move on to another function so I have x amount of memory once again. |
| ||
Are you using proper datatypes? e.g. declare your images as 'timage' instead of 'int'? Do you reload your graphics at the beginning of a level? If so, do you first clear the old variables? And again, is there any reason that you aren't using 1.39? There have been a bunch of bugfixes in the past 5 releases, which might address the issue that you're running into here... |
| ||
e.g. declare your images as 'timage' instead of 'int'? No, I'll do that :) Do you reload your graphics at the beginning of a level? I reload a lot of them, because they're local. I have too many images for them to ALL be global, because then the initial load time is far too long. If so, do you first clear the old variables? Thats what I'm trying to figure out how to do. Would just saying image=null work? And again, is there any reason that you aren't using 1.39? Not really. I was using 1.35, heard it had glitches, downgraded to 1.34 and haven't bothered to upgrade. I probably should, lol. Thanks xlsior! I always find your suggestions invaluable. You are a very knowledgeable fellow :) |
| ||
you may as well upgrade what i do is put my images in an array or a Tmap When you want to get rid of the images just do map=null or array = null your problem probly lies in the fact that you are using Int for Images, that should probably be made more clear to max users. |
| ||
Would just saying image=null work? I think so, BUT make sure that you define them as :timage - I remember reading something about memoryleaks when you don't. |
| ||
Ok, thanks to both of you :) I'm working on dinner right now, and probably won't have the chance to do much tonight, but I'll work tomorrow on replacing all image=LoadImage, with image:timage = LoadImage instead. And then I'll see what else I can do as well. While working on dinner, might as well be download version 1.39 ;) Thanks! |
| ||
Are you using Strict or SuperStrict ? |
| ||
What Brucey said. Also, are you running in release or debug mode? My game doesn't free all the memory in debug mode, but it does in release. |
| ||
e.g. declare your images as 'timage' instead of 'int'? Not using Strict is just asking for your program not to work. No, I'll do that :) |
| ||
Not using Strict is just asking for your program not to work. More specifically: not using strict is asking for these kind of 'mystery' problems, even though things may appear to work just fine at first sight. |
| ||
I'm not using strict ;) I only found out about strict when I was several thousand lines of code in, and really didn't want to go back through all my code defining what type of variable things are ;( I'm running in Debug Mode, although running in Release doesn't fix the problem. I'll work on what I posted above today, and 'maybe' on using Strict :( Thanks! |
| ||
Well if you aren't using strict you aren't using BM either. You are using BlitzBasic compiled on BM basically. You lose some major functionality in relation to object handling and the garbage collector will work worse too. One of the functionalities you are missing is that variable scoping does not exist, so you can save yourself the time to declare local variables as the only "local" that exists is a whole function. Even worse, it offers you another major reason for memory leaks and thats the possibility to get handles from objects which is the worst thing you can do of all (should you really do that, you can be happy that you only have the problems you have), as it does not work with GC anymore then at all |
| ||
As I am not very experienced as well, I started my game without using strict and I had similar issues. I too was thousands of lines and counting, but still went back and converted everything to Superstrict. It's not as scary or hard to do as you might initially think. Running in Debug mode with superstrict still doesn't clear the memory, but in release mode it does. I'd say try convert to superstrict, it makes for cleaner coding as well. |
| ||
Ecch, looks like I must use strict, or superstrict after all then ;( Oh well. I've converted all the image = loadimage to image:Timage = loadimage, and that 'helped' although I'm still losing memory. I also upgraded to version 1.39, and that helped a lot, I'm now only losing memory slowly. I'm also working on making sure all local variables are cleared :) Thanks! |
| ||
yknow you can get the IDE to replace text in the bmx file right? e.g. search for trev=null and replace with trev:Timage=null |
| ||
Yeppers, thats how I fixed the loadimage :) Its still annoying though, lol |
| ||
Set it to strict mode, and I'm now down to line 4025.(Still around 20'000 to go I think). Although its annoying, I can already feel the difference. Strict just gives me so much control, and already pointed out a few minor errors ;) It also pointed out to me a few local variables that I didn't need, and a truly mysterious line of code. If P.Pos = 1 NN = 50 ElseIf P.Pos = 2 NN = -50 End If WTF? Anyways, Strict is awesome :) Thanks again everyone! |
| ||
Superstrict is even better. ;-) |
| ||
Superstrict is even better. ;-) +1 Awaiting UltraStrict, ;) |
| ||
Awaiting UltraStrict, ;) +1Awaiting SuperUltraStrict. |
| ||
strict should have been on by default. But alas, blitzmax is in Super Lax mode by default ;( |
| ||
Personally I use normal Strict! |
| ||
I agree WERDNA, by default maxide should put in strict when creating a new bmx file. I think blide does this when I remember correctly |
| ||
Whenever I come across a really nasty bug I can't pinpoint, I comment out half my code and see if it still exists. If it does, I comment out half again. By this binary culling technique you can often zero in on the problem quite quickly. Not always, however, as sometimes it is a dependency between the commented/uncommented sections that is the source of the problem. Could be worth a try though. I totally agree with the SuperStrict advice above. |
| ||
I use the stack tracer using Blide. I don't know how I survived without it. |
| ||
I've been using Local MA:Int = GCMemAlloced() 'The function or code you want to test for leakage here Print GCMemAlloced() - MA And then right after printing the results, calling and printing GCCollect() to see how much of the memory allocated for that function has been cleaned up. Its really helped me quite a bit, and all I have left is some very minor memory leaks, that I've pinned down to a few functions. So hopefully I'll have this ready soon :) Thanks everyone! |
| ||
From the BMax docs (under tutorials):Local image=LoadImage( "somepic.png" ) 'assigning an object to an int! What gives? However, if you are using this feature in your programs, you *must* later 'free' the object yourself using Release... Release image You can therefore think of Release as being similar to Blitz3D's FreeImage (or FreeSound, FreeThis, FreeThat etc). All-in-all, it's probably best to avoid object-to-int assignments altogther if you are concerned about memory leaks. (emphasis mine) Russell |
| ||
lol. that was a large part of the problem. I was horrified when I realized I was assigning Timages, to an INT. :) |