Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2006-09

memory leak detection using FPC

11 messages · 6 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi,

How do you do memory leak detection using FPC? I know about the -gh parameter, but don't know how to use it, or with what other tools. I develop under Linux on x86.

Regards,
- Graeme -

There's no place like 127.0.0.1

Reply by email

Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 5 lines
Hi, How do you do memory leak detection using FPC? I know about the -gh parameter, but don't know how to use it, or with what other tools. I develop under Linux on x86.

Just add -gh to the compiler command-line.

Run your project from a console, so you can see standard output.

When the program is finished, it will give you a detailed list of memory leaks.

Michael.

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt
Michael Van Canneyt wrote 5 lines
Just add -gh to the compiler command-line. Run your project from a console, so you can see standard output. When the program is finished, it will give you a detailed list of memory leaks.

Oops, so all the lines scrolling off the screen are memory leaks!! I'm in trouble now!

Regards,
- Graeme -

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: Just add -gh to the compiler command-line. Run your project from a console, so you can…

So what is wrong with this code then... When I quit the app, it says I have one memory leak. What am I not freeing?

---------------------------------------------
program memleak;
{$mode objfpc}{$H+}
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, SysUtils;
type
  TMyObject = class(TObject)
  private
    FAge: integer;
    FName: string;
  public
    property Name: string read FName write FName;
    property Age: integer read FAge write FAge;
  end;
var
  lObj: TMyObject;
begin
  lObj := TMyObject.Create;
  try
    lObj.Name := 'Graeme';
    lObj.Age := 123;
    Writeln('Hello ' + lObj.Name + ', you are ' + IntToStr(lObj.Age) +
' years old.');
  finally
    lObj.Free;
  end;
end.
---------------------------------------------

The output:

---------------------------------------------
[graemeg-linux] memoryleakdetection > ./memleak
Hello Graeme, you are 123 years old.
Heap dump by heaptrc unit
24 memory blocks allocated : 471/520
23 memory blocks freed : 431/480
1 unfreed memory blocks : 40
True heap size : 393216 (32 used in System startup) True free heap : 393072
Should be : 393088
Call trace for block $B7EB61B0 size 40
$08070E6D
$080480AB
---------------------------------------------

Compiler options: -S2cgi -OG1 -gl -gh -vewnhi -l -Fu. -omemleak

Regards,
- Graeme -

Michael Van Canneyt wrote 5 lines
Just add -gh to the compiler command-line. Run your project from a console, so you can see standard output. When the program is finished, it will give you a detailed list of memory leaks. Michael.
There's no place like 127.0.0.1

Reply by email

Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote
So what is wrong with this code then... When I quit the app, it says I have one memory leak. What am I not freeing?

Try putting everyting in a procedure 'Test' and run that.

Global variables (even temporary ones) may not yet have been deallocated when the debugger output is written. By putting everything in a procedure, you force deallocation of all used variables, implicit or not.

Michael.

Show quoted text 76 lines
--------------------------------------------- program memleak; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, SysUtils; type TMyObject = class(TObject) private FAge: integer; FName: string; public property Name: string read FName write FName; property Age: integer read FAge write FAge; end; var lObj: TMyObject; begin lObj := TMyObject.Create; try lObj.Name := 'Graeme'; lObj.Age := 123; Writeln('Hello ' + lObj.Name + ', you are ' + IntToStr(lObj.Age) + ' years old.'); finally lObj.Free; end; end. --------------------------------------------- The output: --------------------------------------------- [graemeg-linux] memoryleakdetection > ./memleak Hello Graeme, you are 123 years old. Heap dump by heaptrc unit 24 memory blocks allocated : 471/520 23 memory blocks freed : 431/480 1 unfreed memory blocks : 40 True heap size : 393216 (32 used in System startup) True free heap : 393072 Should be : 393088 Call trace for block $B7EB61B0 size 40 $08070E6D $080480AB --------------------------------------------- Compiler options: -S2cgi -OG1 -gl -gh -vewnhi -l -Fu. -omemleak Regards, - Graeme - On 19/09/06, Michael Van Canneyt wrote: > Just add -gh to the compiler command-line. > Run your project from a console, so you can see standard output. > When the program is finished, it will give you a detailed list of memory > leaks. > > Michael. -- There's no place like 127.0.0.1 _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Jonas Maebe
to Graeme Geldenhuys: So what is wrong with this code then... When I quit the app, it says I have one memory…
Graeme Geldenhuys wrote
So what is wrong with this code then... When I quit the app, it says I have one memory leak. What am I not freeing?

If you compile the rtl with line info, you'll see the non-freed object is in the RTL:

Call trace for block $00187260 size 60
$0000E284 line 180 of /Users/jonas/fpc/rtl/inc/objpas.inc $0000F070 line 724 of /Users/jonas/fpc/rtl/inc/objpas.inc $00052158 line 16 of /Users/jonas/fpc/rtl/objpas/sysutils/ sysuthrd.inc
$00039F0C line 1658 of /Users/jonas/fpc/rtl/objpas/classes/ classes.inc

Line 1658 of classes.inc is

   GlobalNameSpace := TMultiReadExclusiveWriteSynchronizer.Create;

in the procedure CommonInit. In CommonCleanup it does:

   { GlobalNameSpace is an interface so this is enough }
   GlobalNameSpace:=nil;

but apparently this is either not enough, or there is a bug with interface reference counting (the latter is possible, since I've read more things about that lately).

Jonas

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: Try putting everyting in a procedure 'Test' and run that. Global variables (even…

Hi Michael,

Try putting everyting in a procedure 'Test' and run that.

I did that and still see the unfreed memory error. I think Jonas might be onto something.

I used the tiBaseObject unit from tiOPF. It has memory leak detection (derived from the IndySOAP project), but only if your classes decend from TtiBaseObject. When I use that, it gives no errors, but if Jonas is right, that is understandable, as the tiBaseObject only checks objects I create and not things in the RTL.

Regards,
- Graeme -

Reply by email

Vincent Snijders
to Jonas Maebe: If you compile the rtl with line info, you'll see the non-freed object is in the RTL:…
Jonas Maebe wrote 27 lines
On 19 sep 2006, at 09:33, Graeme Geldenhuys wrote: > So what is wrong with this code then... When I quit the app, it says > I have one memory leak. What am I not freeing? If you compile the rtl with line info, you'll see the non-freed object is in the RTL: Call trace for block $00187260 size 60 $0000E284 line 180 of /Users/jonas/fpc/rtl/inc/objpas.inc $0000F070 line 724 of /Users/jonas/fpc/rtl/inc/objpas.inc $00052158 line 16 of /Users/jonas/fpc/rtl/objpas/sysutils/sysuthrd.inc $00039F0C line 1658 of /Users/jonas/fpc/rtl/objpas/classes/classes.inc Line 1658 of classes.inc is GlobalNameSpace := TMultiReadExclusiveWriteSynchronizer.Create; in the procedure CommonInit. In CommonCleanup it does: { GlobalNameSpace is an interface so this is enough } GlobalNameSpace:=nil; but apparently this is either not enough, or there is a bug with interface reference counting (the latter is possible, since I've read more things about that lately).

See also http://www.freepascal.org/mantis/view.php?id=7357.

Graeme, if you use fpc 2.1.1, then memleak of 40 bytes is not your fault.

Vincent

Reply by email

Inoussa OUEDRAOGO
to Jonas Maebe: If you compile the rtl with line info, you'll see the non-freed object is in the RTL:…

hi
I reported a bug for interface reference counting at http://www.freepascal.org/mantis/view.php?id=7281

Bellow is the test program.

Regards, Inoussa.

====================
program test_intf;
{$mode objfpc}{$H+}
uses
  SysUtils;
type
  ITest = interface
    procedure DoIt(AMsg : string);
  end;
  TTest = class(TInterfacedObject,ITest)
  protected
    procedure DoIt(AMsg : string);
  public
    constructor Create();
    destructor Destroy();override;
  end;
var InstancesCount : Integer = 0;
procedure TTest.DoIt(AMsg: string);
begin
  WriteLn(AMsg);
end;
constructor TTest.Create();
begin
  Inherited;
  Inc(InstancesCount);
  WriteLn('Creating >>> ',Integer(self));
end;
destructor TTest.Destroy();
begin
  Dec(InstancesCount);
  WriteLn('Destroying >>> ',Integer(self));
  inherited Destroy();
end;
procedure proc1(ATest : ITest);
begin
  ATest.DoIt('  called in proc1');
end;
procedure test();
begin
  (TTest.Create() as ITest).DoIt('  called in test');
  proc1(TTest.Create() as ITest);
end;
begin
  test();
  WriteLn('Remaining instances ... ',InstancesCount);
end.

Reply by email

Leonardo M. Ram�
to Inoussa OUEDRAOGO

That's true, because of that i don't use interfaces in FPC, instead i use virtual abstract classes.

--- Inoussa OUEDRAOGO wrote 70 lines
hi I reported a bug for interface reference counting at http://www.freepascal.org/mantis/view.php?id=7281 Bellow is the test program. Regards, Inoussa. ==================== program test_intf; {$mode objfpc}{$H+} uses SysUtils; type ITest = interface procedure DoIt(AMsg : string); end; TTest = class(TInterfacedObject,ITest) protected procedure DoIt(AMsg : string); public constructor Create(); destructor Destroy();override; end; var InstancesCount : Integer = 0; procedure TTest.DoIt(AMsg: string); begin WriteLn(AMsg); end; constructor TTest.Create(); begin Inherited; Inc(InstancesCount); WriteLn('Creating >>> ',Integer(self)); end; destructor TTest.Destroy(); begin Dec(InstancesCount); WriteLn('Destroying >>> ',Integer(self)); inherited Destroy(); end; procedure proc1(ATest : ITest); begin ATest.DoIt(' called in proc1'); end; procedure test(); begin (TTest.Create() as ITest).DoIt(' called in test'); proc1(TTest.Create() as ITest); end; begin test(); WriteLn('Remaining instances ... ',InstancesCount); end. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Leonardo M. Ramé
http://leonardorame.blogspot.com

__________________________________________________ Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

Reply by email