[Lazarus] Memory leak with Synchronize on external threads

Stefan Schalk schalk.stefan at googlemail.com
Tue May 31 14:37:30 CEST 2016


 

   Hi everybody,

 

for the demonstration of the memory leak I created a small application.

This makes it easier to reproduce.

 

The demo starts threads - one after another.

A timer will trigger the thread starts.

The timer waits for the previously started thread to finish, cleans up and
starts a new thread.

The thread's function will only forward to a method of the main form by using
"TThread.Synchronize".

The method in the main form will increase a counter and shows it in a label.

That's all.

 

While running the application you can observe the increasing memory consumption
with MS Taskmanager, Proccess Explorer or the like.

 

To create the demo application use Lazarus 1.6 and place a TLabel and a TTimer
component on your main form.

The timer gets an interval of 200ms and is initially disabled.

 

If you use TThread.Synchronize call, memory will start to leak.

Without the snycronize call there is no leak.

 

Can anybody acknowledge my finding?

Is there already a fix for this?

 

Best regards,

Stefan

 

 

 

// - - - - - Start of the demo code - - - - -

unit main;

 

{$mode objfpc}{$H+}

 

interface

 

uses

  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ExtCtrls

  {, JwaPsApi, JwaWinBase};

 

type

  TForm1 = class(TForm)

    Counter_Label: TLabel;

    //Memory_Label: TLabel;

    Timer1: TTimer;

    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);

    procedure FormCreate(Sender: TObject);

    procedure FormShow(Sender: TObject);

    procedure SyncExecute;

    procedure Timer1Timer(Sender: TObject);

  private

    FCounter    : Integer;

    FmyThreadID : TThreadID;

  end;

 

var

  Form1: TForm1;

 

implementation

 

{$R *.lfm}

 

procedure TForm1.FormCreate(Sender: TObject);

begin

  FCounter    := 0;

  FmyThreadID := 0;

end;

 

procedure TForm1.FormShow(Sender: TObject);

begin

  Timer1.Enabled := true;

end;

 

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);

begin

  Timer1.Enabled := false;

  if FmyThreadID <> 0 then

  begin

    WaitForThreadTerminate(FmyThreadID, 2000);

    CloseThread(FmyThreadID);

    FmyThreadID := 0;

  end;

  CloseAction := caFree;

end;

 

procedure TForm1.SyncExecute;

begin

  Inc(FCounter);

  Counter_Label.Caption := IntToStr(FCounter);

end;

 

function myThreadFunc(parameter : pointer) : ptrint;

begin

  TThread.Synchronize(nil, @Form1.SyncExecute);

  EndThread;

end;

 

procedure TForm1.Timer1Timer(Sender: TObject);

//var

//  pmc: _PROCESS_MEMORY_COUNTERS;

begin

  Timer1.Enabled := false;

 

  if FmyThreadID <> 0 then

  begin

    WaitForThreadTerminate(FmyThreadID, 2000);

    CloseThread(FmyThreadID);

    FmyThreadID := 0;

  end;

  FmyThreadID := BeginThread(@myThreadFunc, nil);

{

  pmc.cb := SizeOf(pmc);

  if GetProcessMemoryInfo(GetCurrentProcess(), pmc, pmc.cb) then

  begin

    Memory_Label.Caption := IntToStr(pmc.WorkingSetSize) + ' Bytes';

  end

  else Memory_Label.Caption := 'Unable to get process info!';

}

  Timer1.Enabled := true;

end;

 

end.

// - - - - - End of the demo code - - - - -

 

 

 

 

Von: Stefan Schalk [mailto:schalk.stefan at googlemail.com] 
Gesendet: Donnerstag, 26. Mai 2016 11:07
An: Lazarus Mailing List <lazarus at lists.lazarus.freepascal.org>
Betreff: [Lazarus] Memory leak with Synchronize on external threads

 

There is a memory consumption/leak using the TThread.Synchronize function.

A callback function is called out of another ("external") thread (from an
loaded DLL).
Inside the callback function a synchronized call to a procedure has to be done.
Every thing works without error, but there is a memory use increasement during
the TThread.Synchronize call.

procedure OnExternalThreadCallback(...); cdecl;
begin
  ...
  TThread.Synchronize(nil, @MyMainClass.CallbachSyncedWithMainThread);
  ...
end;

The external thread are created/used/freed like discussed in the Lazarus
mailing list:
Mutlithreaded Dll Callback crashes my Application
<http://lists.lazarus.freepascal.org/pipermail/lazarus/2010-August/054728.html> 

The memory leak problem arises with Lazarus 1.6.0 and FPC 3.0.0.
Under the hood the processing of the TThread.Synchronize changed.
Lazarus 1.4.4 with FPC 2.6.4 didn't have this problem.
I don't have the versions between 1.4.4 and 1.6.0, therefore I cannot say
something about them (if there are any).

 

 

 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: winmail.dat
Type: application/ms-tnef
Size: 12762 bytes
Desc: not available
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20160531/7c8457e5/attachment-0002.bin>


More information about the Lazarus mailing list