[fpc-pascal] Possible Memory Leak in TThread.Synchronize
Tony Whyman
tony.whyman at mccallumwhyman.com
Wed Jan 3 12:31:53 CET 2018
I have been investigating a possible memory leak in a multi-threading
Lazarus program compiled with 3.0.4 where the stack trace with heaptrc
shows:
Heap dump by heaptrc unit
7014 memory blocks allocated : 131978472/131992352
7004 memory blocks freed : 114543216/114557096
10 unfreed memory blocks : 17435256
True heap size : 19267584
True free heap : 1831200
Should be : 1831048
Call trace for block $00007FFFE2A9D0C0 size 96
$000000000043B31A line 354 of ../inc/heap.inc
$0000000000450FE8 line 888 of ../unix/cthreads.pp
$000000000043DB9F line 294 of ../inc/thread.inc
$00000000004AE6B4 line 322 of ../objpas/classes/classes.inc
$00000000004AE754 line 344 of ../objpas/classes/classes.inc
$00000000004AE7F0 line 357 of ../objpas/classes/classes.inc
....
Line 322 of classes.inc reads:
FSynchronizeEntry^.SyncEvent := RtlEventCreate;
Hence the implication is that the SyncEvent is not being disposed of
correctly. Later on TThread.DoneSynchronizeEvent reads
procedure TThread.DoneSynchronizeEvent;
begin
if not Assigned(FSynchronizeEntry) then
Exit;
RtlEventDestroy(FSynchronizeEntry^.SyncEvent);
Dispose(FSynchronizeEntry);
FSynchronizeEntry := Nil;
end;
So no problem here it seems. However, investigating further, this is not
the only place that a SynchronizeEvent is disposed of. At line 379 of
classes.inc we see:
function CheckSynchronize(...)
and this ends with:
else
begin
{ for Queue entries we dispose the entry and raise the exception }
Dispose(tmpentry);
if Assigned(exceptobj) then
raise exceptobj;
end;
tmpentry := PopThreadQueueHead;
end;
The line "Dispose(tmpentry);" also disposes of a SynchronizeEvent but,
unlike TThread.DoneSynchronizeEvent, there is no RtlEventDestroy.
Am I correct in pointing the finger here for the memory leak?
Tony Whyman
MWA
More information about the fpc-pascal
mailing list