Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory leak in Free Pascal caused by methods with 'pointer' parameter

After replacing hard type casts of AnsiString to TBytes (array of string) with a ToBytes method (see below), Delphi reported no memory leaks - Free Pascal 2.6.2 however shows a leak in case the TBytes value is passed to a method with a parameter of type Pointer.

The following code leaks memory:

program project1;

{$mode delphi}

uses
  SysUtils;

function ToBytes(const AValue: AnsiString): TBytes;
begin
  SetLength(Result, Length(AValue)); // <-- leak (ine 10)
  if Length(AValue) > 0 then
    Move(AValue[1], Result[0], Length(AValue));
end;

procedure Send(P: Pointer);
begin

end;

begin
  Send(ToBytes('test'));

  SetHeapTraceOutput('heaptrace.log');
end. 

Memory leak report:

Call trace for block $001C5CC0 size 12   $00401586  TOBYTES,  line 10
of project1.lpr   $00401622  main,  line 21 of project1.lpr

If I change the Send method to take an argument of type TBytes, the memory leak disappears.

like image 374
mjn Avatar asked Mar 04 '14 19:03

mjn


2 Answers

That's a compiler bug. The managed type TBytes has reference counted lifetime. The compiler should create an implicit local variable which is assigned the array returned by ToBytes. You'll need to work around that by storing to an explicit local:

var
  Tmp: TBytes;
....
Tmp := ToBytes(...);
Send(Tmp);
like image 118
David Heffernan Avatar answered Sep 30 '22 13:09

David Heffernan


It is probably not a bug where you think it is. The heap tracing of FPC has known issues with tracking temps (and automated types in general) in main programs (the main .dpr begin..end).

Move the code to a procedure, and call that from the main begin..end. and you'll see the leak disappears.

This because the general structure of the main program is like

begin 
  initializeunits(); // procedure call inserted by the compiler
    <actual mainprogram statements>
  finalizeunits();   // procedure call inserted by the compiler
end.

with the releasing of mainprogram temps happening at "end." after finalizeunits that finalizes the heaptracking. (even if it is first unit, it is still only an unit). So heaptrc misses that.

like image 38
Marco van de Voort Avatar answered Sep 30 '22 15:09

Marco van de Voort