Update: The changes to introduce VCL styles in XE2 have removed the memory leak. So I guess it was unintentional after all.
I came across a VCL memory leak today, in Themes.pas. It only occurs for DLLs. The unit finalization code is as so:
finalization
if not IsLibrary then
InternalServices.Free;
InternalServices
is a singleton that is created on demand when you call the ThemeServices
function. Many DLLs do not have UI and so do not ever create this singleton. However, I happen to have a COM add-in to Excel which does result in this leak manifesting.
The leak doesn't particularly bother me because this DLL is never repeatedly loaded and unloaded from the same process. And I know how I could fix the leak using the ThemeServicesClass
global variable.
My question though, is to ask if anyone can explain why this code is the way it is. It seems quite deliberately coded this way. For the life of me I cannot come up with an explanation for this intentional leak.
One explanation is that the unit finalization section is executed while the OS loader lock is active. During that time, there are significant restrictions on what a DLL is allowed to do without risking deadlock.
We run into this same problem as well. Here is what we are currently doing to prevent the leak in our projects:
In the dll .dpr file add Themes to the uses section.
Add the following to clean up the leak on shutdown:
procedure DLLEntryProc(EntryCode: integer);
begin
case EntryCode of
DLL_PROCESS_DETACH:
begin
ThemeServices.Free;
end;
DLL_PROCESS_ATTACH:
begin
end;
DLL_THREAD_ATTACH:
begin
end;
DLL_THREAD_DETACH:
begin
end;
end;
end;
begin
{$IFDEF DEBUG}
ReportMemoryLeaksOnShutdown := True;
{$ENDIF}
DllProc := @DLLEntryProc;
end.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With