Jump to content
Thomas B

Memory Leak when loading/unloading Delphi DLL

Recommended Posts

I have a weird problem with a memory leak caused by a DLL written in Delphi.

 

As a test I have a C++ application that loads and unloads the DLL in a loop:

HINSTANCE lib;
while(1)
{
	lib = LoadLibraryA("MyLib.dll");
	FreeLibrary(lib);
}

When I look at the memory usage either in Task Manager or Visual Studio Memory Diagnostics, I can see that memory usage keeps growing indefinitely.

 

Originally I thought it was caused by a leak in my Delphi code. But eventually I reduced it to:

library MyLib;
uses System.SysUtils;
end.

And the memory leak still appears. Only if I remove "uses System.SysUtils;" the leak is gone.

 

I have tried to compile the DLL with Delphi XE2 and Delphi 11. The behaviour is the same.

 

Does anyone know what causes this? Is there anything I can do (maybe some compiler settings?) to avoid the memory leak?

Edited by Thomas B

Share this post


Link to post

At what point you confirm that you having a memory leak?

Beside that you do not check for anything (what you should do) your infinite loop loads faster than it release, but ref counting works correct here.

Share this post


Link to post

Do not watch Task Manager to diagnose memory leaks. Windows often doesn't release the memory what the application is not using anymore but keeps it to speed up future memory allocations.

I don't know if FastMM (ReportMemoryLeaksOnShutdown) will report a leak in a DLL, but you can request a trial of DeLeaker which will show you everything for sure.

 

There's one thing for sure - there's no memory leak in System.SysUtils in the initialization / finalization section.

Share this post


Link to post
On 2/11/2023 at 7:28 PM, aehimself said:

Do not watch Task Manager to diagnose memory leaks. Windows often doesn't release the memory what the application is not using anymore but keeps it to speed up future memory allocations.

I don't know if FastMM (ReportMemoryLeaksOnShutdown) will report a leak in a DLL, but you can request a trial of DeLeaker which will show you everything for sure.

 

There's one thing for sure - there's no memory leak in System.SysUtils in the initialization / finalization section.

I did not only use Task Manager, I also used the built-in memory profiler in Visual Studio.

 

I know that Windows keeps around some memory. I did the same test with a DLL written in C/C++ and the memory usage grows up to around ~300KB then further LoadLibrary/FreeLibrary calls seem to reuse previous memory and the overall memory usage does not continue to grow. But that is not the case for the Delphi DLL. After running it for half an hour or so, the memory usage was already at a few houndred MB and it showed no sign of stopping.

 

I tried using FastMM (ReportMemoryLeaksOnShutdown), but it did not show any leaks. Visual Studio memory profiler shows the allocations for each call but it only hints at "external code" and some memory address. According to the memory snapshots there are around ~5KB of memory allocations for each LoadLibrary call, that are not freed with FreeLibrary.

 

All I can say for sure is that if I remove "uses System.SysUtils" the problem is gone, which is obviously not a fix, since I want to use some of the functionality.

Share this post


Link to post

You should probably enter a bug report at https://quality.embarcadero.com. Don't forget to attach your MSVC test program (Entire solution) and the Delphi DLL complete project. with a good report, chances are that it is tested quickly. Once the report is created, provide the link here.

Share this post


Link to post
On 2/13/2023 at 9:28 AM, FPiette said:

You should probably enter a bug report at https://quality.embarcadero.com. Don't forget to attach your MSVC test program (Entire solution) and the Delphi DLL complete project. with a good report, chances are that it is tested quickly. Once the report is created, provide the link here.

Thank you, I didn't know that existed. I will create a bug report and link it here when done.

 

On 2/13/2023 at 10:05 AM, Fr0sT.Brutal said:

Will the bug show when host app is built with Delphi? It would significantly simplify case reproducing

Yes I just recreated the same behaviour with the host application written in Delphi. Here is the full code:

program app;

{$APPTYPE CONSOLE}

uses Winapi.Windows;

var
    lib: HMODULE;
    res: Boolean;
begin
    while True do
    begin
        lib := LoadLibraryA('lib.dll');
        if lib = 0 then
        begin
            WriteLn('LoadLibraryA failed');
            Exit;
        end;
        
        res := FreeLibrary(lib);
        if res = False then
        begin
            WriteLn('FreeLibrary failed');
            Exit;
        end;
        
        lib := 0;
    end;
end.

 

Edited by Thomas B
  • Like 1

Share this post


Link to post

I have not been able to reproduce the problem using the supplied DLL and host source.

Compiled with Delphi 11.2 targeting both 32- and 64-bit.

Virtual memory, private bytes, working set, and handles were stable. No leaks were identified.

 

I suggest you test it on a clean system (or do a secure boot) to ensure that stuff isn't being injected into your process (e.g. via HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs).

Share this post


Link to post
On 2/13/2023 at 8:57 AM, Thomas B said:

I tried using FastMM (ReportMemoryLeaksOnShutdown), but it did not show any leaks.

I tried your newest Delphi console penetration test, no leaks no errors.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×