Log in

View Full Version : Memory leaks



NecroDOME
10-03-2006, 03:04 PM
I came accross this:

A unit that checks for memory leaks in your program.

http://v.mahon.free.fr/pro/freeware/memcheck/

May come handy sometimes...

Traveler
10-03-2006, 04:11 PM
Looks very interesting! I've been meaning to ask earlier, but since you brought the topic up, does anyone know of similar tools?

cairnswm
10-03-2006, 06:45 PM
A long time ago I used to use a unit called Snoop - I doubt its been updated but it might still be around.

AthenaOfDelphi
10-03-2006, 07:53 PM
The one I use most is MemProof (http://www.automatedqa.com/products/memproof/index.asp).

I have also used SleuthQA from the now defunct TurboPower, I believe its now available as a public download.

aidave
10-03-2006, 08:55 PM
i never have memory leaks

:roll:

NecroDOME
10-03-2006, 09:58 PM
i never have memory leaks

How are you so sure? Have you ever tested your programs ?

Traveler
10-03-2006, 10:13 PM
i never have memory leaks

How are you so sure? Have you ever tested your programs ?

I dont think that was a serious reply from aidave :)


Thanks for the links, I shall give them all a try. :thumbup:

WILL
11-03-2006, 12:14 AM
Excellent! :) I am the king of memory leaks. :king:

I think I'll give this bad-boy a go in my latest game project. How heafty is it in your programs?

JSoftware
13-03-2006, 02:45 PM
What about a little memory leak contest? :roll:

User137
13-03-2006, 07:47 PM
1 question i'm not sure of... If i have a class:


TSomeClass = class
public
text: TStringList;
constructor Create;
end;
Then i create StringList in constructor. Will it be freed if i free TSomeClass object? or if i don't even free it, will it leave in memory when app closes?
I would find it hard to imagine WinXP could not handle and free application's own memory spaces.

Robert Kosek
13-03-2006, 08:05 PM
You must free the image yourself, override the destroy procedure and add in the freeing in there.

technomage
13-03-2006, 09:43 PM
I would find it hard to imagine WinXP could not handle and free application's own memory spaces.

I think the memory is recovered when the app closes on most modern OS's. But if you don't worry about memory management while you app is running your app will probably run out of memory while running, especially if you are creating lots of objects but not freeing them.

User137
14-03-2006, 02:14 AM
You must free the image yourself, override the destroy procedure and add in the freeing in there.

That would be too obvious :wink: But isn't TForm freeing its child objects too, so why not other objects? Maybe its destructor just has a loop that frees them all, or maybe the thing i read some point was all about application closing. I'm just playing around with the idea finding the limitations...not that i would leave the .Free's uncalled :D Delphi is quite high level language already with much automation.

Robert Kosek
14-03-2006, 02:51 AM
If you don't free it, it's not freed. So if you free a class with sub-objects that aren't freed in your Destroy() destructor, you'll have a substantial block of allocated memory remain.

... Are you trying to follow in Adobe's footsteps? :P

cairnswm
14-03-2006, 05:24 AM
Basicaly the rule in Delphi is - if you create something you must destroy it.

While TForm distroys each of its child components you must remember that each Child Object is included in the Components list of the form. Therefore the Form knows about the components and can then destroy them each as it closes.

When you create a stringlist inside another class the class itself does not actually know about the string list (it only contains it) and therefore does not know that it needs to destroy it.

When I create a 'Map' object in my games I will typically register all child objects into the Map

TBaseItem = Class;

TMap = Class
Items : TList;
Constructor Create;
Destructor Destroy;
Procedure AddItem(NewItem : TBaseItem);
End;

TBaseItem = Class
Map : TMap;
End;


So Whenever a new item is created the Map.AddItem is called which adds it to the Items list.

When the Map is freed

Destructor TMap.Destroy;
Var I : Integer;
Begin
For Items.Count-1 downto 0 do
Begin
TBaseItem(Items[I]).Free;
End;
End;


Which ensures that the Map frees all the items in the same way that a form frees all the components that are on it.


If you create an instance of a class, you are responsible for freeing it.

michalis
14-03-2006, 06:13 AM
(This thread is under Delphi, but I couldn't resist to mention here how it's for FPC.)

FPC already includes memory leaking unit, it's called HeapTrc. You can explicitly add it to your uses clause (just like some other mem leaker detectors for Delphi, since they should work with FPC as long as they do not depend on any Delphi internals). You can also just compile your program with -gh command-line option, this implicitly adds HeapTrc to your uses clause (this is handy, because this way you don't have to edit source code to turn mem leaking detecting on; you only change the FPC command-line, or "Compiler Options" in Lazarus).

There is also a related option -gc that activates pointer checking. And another related option is -gl, this inserts line information into your executable. Together all these options will notify you about any access to wrong place in the memory (without them, it's never guaranteed that you will get segfault), and any memory leak. And you will get backtrace telling you exactly where you tried to access invalid pointer or where you allocated memory that was left unallocated at program exit.

So if you're using FPC, it's highly adviced to compile all debug code with -gh -gl options. -gc is also great, although in some cases it can slow down the code too much.



That would be too obvious Wink But isn't TForm freeing its child objects too, so why not other objects?


cairnswm already explained it, I'll just say it once again using different words:

Every descendant of TComponent (like TForm) frees all the objects it "owns". One component is an owner of another when it's passed as the AOwner parameter to the constructor. This means that when you create MyObject like


MyObject := TMyObject.Create(MyOwnerObject);


then MyObject will be automatically freed when MyOwnerObject will be freed. All you have to do for this is to make MyObject and MyOwnerObject classes descend from TComponent.

You can also use TObjectList class, it will automatically free it's items when OwnsObjects is true.

tpascal
14-03-2006, 03:40 PM
Have anyone tried this memcheck unit?,

I did a litle test in regular delphi project (I mean using Dpr, forms and unit1.pas), i added a button to the form and in the onclick button event i added:





procedure TForm1.Button1Click(Sender: TObject);
var
p:pointer;
begin
getmem(p,64*1024);
end;



I have placed memchk procedure call in the form create event, then when the program is running, for each click in the button a 64kb memomy block is allocated; when i close the program the memcheck indeed informs me accurately the amount bytes allocated (and never released meanwhile the program was running); it also tells me that i used Getmem for allocate the memory however the unit is unable to show me where in my source code i am allocating that memory.

I have enabled the debugger and turned On the stack frames and all debug options in the project options (as the unit's documentation tells), then i tried again but still there is not easy way to found that the problem happen in my onclick code in unit1.pas, the debugger opens system.pas and stops in a line inside, seem procedure getmem() calls lot sub procedures/functions, in fact the checkmem reports 21 stacks calls, (mean since i click the button then about 21 procedures/functions are called in the procces).

Yes, knowing your program is leaking memory is very usefull, but also knowing where it happen in your code should be a MUST, specially in biggers projects like a video game;

how you guys usually found where you have the problem in your code?

thank you,

tp.

JSoftware
17-03-2006, 11:14 AM
Haven't found any memoryleaks in my code yet but they are probably there...

Nitrogen
17-03-2006, 05:50 PM
Hey, I've been using Memchk for some time now.

I actually used it on my Chrome plugin for FLStudio..

To get it to give you a location in your code,
like the documentation says:
Go to Project -> Options -> Compiler Tab:

- Disable Optimisation
- Enable Stack-frames
- But here is the important one:
You must go to the Linker tab and enable 'Include TD32 Debug Info'


Project -> Build (This is important!)

This will make your exe about 6mb big, so only use it for testing obviously!

tpascal
17-03-2006, 07:07 PM
Project -> Build (This is important!)


That's what i was mising!, i was just using f9 for compile and run the app.
After doing "projects,build" now the memchecks is able to tell me the unit and the line number where i allocated the memory block, :-)

thank you, this tool is really usefull and easy to use. :D

tp.

technomage
18-03-2006, 09:10 AM
I know we already have a memory checker listed here, but I aways use Snoop http://rmarshsj.f2s.com/rob/2001/06/18/snoop-memory-leak-sniffer/

It's a really nice little tool for Delphi. :D

LP
18-03-2006, 05:58 PM
In Delphi 2006 you can enable memory leak detection by adding this line at program start:


ReportMemoryLeaksOnShutdown:= True;


The above has been implemented from Fast Memory Manager for Delphi, which also provides the feature (you have to turn debug mode ON in options file). It can also detect other things, like modifying a released part of memory and so on.

NecroDOME
19-03-2006, 01:56 PM
Cool, I need to update to delphi 2006

tux
19-03-2006, 02:12 PM
heres some sample output from the delphi 2006 one, not very helpfull :/

---------------------------
Unexpected Memory Leak
---------------------------
An unexpected memory leak has occurred. The unexpected small block leaks are:



13 - 20 bytes: TList x 20, TFinateStateMachine x 20, TGameObjects x 1, Unknown x 12

101 - 108 bytes: TExitLevelPowerUp x 1, THealthPowerUp x 1

109 - 116 bytes: TBarrel x 6, TTurret x 6

149 - 156 bytes: TNPCTank x 5, TUserTank x 1

173 - 188 bytes: Unknown x 1


---------------------------
OK
---------------------------


uh oh spagettii oh!