Memory Leak!!!!!

BlitzMax Forums/BlitzMax Programming/Memory Leak!!!!!

WERDNA(Posted 2010) [#1]
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.


Thareh(Posted 2010) [#2]
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



slenkar(Posted 2010) [#3]
you might be dividing by zero, make sure you are not first,


WERDNA(Posted 2010) [#4]
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 ;)


Czar Flavius(Posted 2010) [#5]
See if it gobbles up tons of memory in the task manager.


xlsior(Posted 2010) [#6]
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...


JoshK(Posted 2010) [#7]
Compile in multithreaded mode. If the leak is fixed, you probably have a circular reference not getting collected in single-threaded mode.


ziggy(Posted 2010) [#8]
JoshK is one of the easiest ways to ensure it is not a circular reference bug.


WERDNA(Posted 2010) [#9]
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 :)


WERDNA(Posted 2010) [#10]
Well multithreaded build didn't work. I'm still losing massive chunks of memory :(


Brucey(Posted 2010) [#11]
Also is there anyway to ADD to the free physical memory?

Put in some new RAM sticks ? :-)


WERDNA(Posted 2010) [#12]
lol


WERDNA(Posted 2010) [#13]
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.


xlsior(Posted 2010) [#14]
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...


WERDNA(Posted 2010) [#15]
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 :)


slenkar(Posted 2010) [#16]
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.


xlsior(Posted 2010) [#17]
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.


WERDNA(Posted 2010) [#18]
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!


Brucey(Posted 2010) [#19]
Are you using Strict or SuperStrict ?


Grafos(Posted 2010) [#20]
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.


Czar Flavius(Posted 2010) [#21]
e.g. declare your images as 'timage' instead of 'int'?

No, I'll do that :)
Not using Strict is just asking for your program not to work.


xlsior(Posted 2010) [#22]
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.


WERDNA(Posted 2010) [#23]
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!


Dreamora(Posted 2010) [#24]
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


Grafos(Posted 2010) [#25]
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.


WERDNA(Posted 2010) [#26]
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!


slenkar(Posted 2010) [#27]
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


WERDNA(Posted 2010) [#28]
Yeppers, thats how I fixed the loadimage :)

Its still annoying though, lol


WERDNA(Posted 2010) [#29]
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!


xlsior(Posted 2010) [#30]
Superstrict is even better. ;-)


therevills(Posted 2010) [#31]
Superstrict is even better. ;-)


+1

Awaiting UltraStrict, ;)


plash(Posted 2010) [#32]
Awaiting UltraStrict, ;)
+1
Awaiting SuperUltraStrict.


WERDNA(Posted 2010) [#33]
strict should have been on by default.
But alas, blitzmax is in Super Lax mode by default ;(


Czar Flavius(Posted 2010) [#34]
Personally I use normal Strict!


Dreamora(Posted 2010) [#35]
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


DavidDC(Posted 2010) [#36]
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.


Czar Flavius(Posted 2010) [#37]
I use the stack tracer using Blide. I don't know how I survived without it.


WERDNA(Posted 2010) [#38]
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!


Russell(Posted 2010) [#39]
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


WERDNA(Posted 2010) [#40]
lol. that was a large part of the problem. I was horrified when I realized
I was assigning Timages, to an INT. :)