How to configure FastMM to detect memory leak in a dll

balazs picture balazs · Jul 4, 2013 · Viewed 8.4k times · Source

I can't figure out how to detect memory leaks in a statically or even dynamically linked dll. I just want to detect the leaks in the dll, and I don't want to share the memory manager between the dll, and the app. Additionally the dll is linked with runtime packages

My sample dll looks like this:

library dll;
uses
  fastmm4,
  System.SysUtils,
  System.Classes;
{$R *.res}
procedure MyInit; stdcall;
Begin
  TObject.Create;
End;
exports MyInit;
begin
end.

application dpr:

program app;

uses
  //fastmm4,
  Vcl.Forms,
  main in 'main.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Note: If I uncomment fastmm4, than I can detect the memleak caused by the application (TStringList.Create), but not the leak in the dll.

And in the application main unit:

unit main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    LDLLHandle: HModule;
    LShowProc: TProcedure;
  end;

var
  Form1: TForm1;

{$ifdef static}
procedure MyInit; stdcall; external 'dll.dll';
{$endif}

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  TStringList.Create;
  {$ifdef static}
  MyInit;
  {$else}
  LDLLHandle := LoadLibrary('dll.dll');
  if LDLLHandle <> 0 then
  begin
    try
      LShowProc := GetProcAddress(LDLLHandle, 'MyInit');
      if Assigned(LShowProc) then
        LShowProc;
    finally
      FreeLibrary(LDLLHandle);
    end;
  end;
  {$endif}
end;

end.

I expect from FastMM to generate a report when FreeLibrary is called, or on program exit, if the dll is statically loaded, but nothing happens.

In the FastMM4Options.inc I additionally just set FullDebugMode and ClearLogFileOnStartup, and the FastMM_FullDebugMode.dll is in the output directory.

I created a repository on github. What am I missing?

Answer

David Heffernan picture David Heffernan · Jul 5, 2013

The reason that your DLL is not reporting leaks stems from this code in the FastMM shutdown:

  CheckBlocksOnShutdown(
  {$ifdef EnableMemoryLeakReporting}
        True
    {$ifdef RequireIDEPresenceForLeakReporting}
        and DelphiIsRunning
    {$endif}
    {$ifdef RequireDebuggerPresenceForLeakReporting}
        and ((DebugHook <> 0)
        {$ifdef PatchBCBTerminate}
        or (Assigned(pCppDebugHook) and (pCppDebugHook^ <> 0))
        {$endif PatchBCBTerminate}
        )
    {$endif}
    {$ifdef ManualLeakReportingControl}
        and ReportMemoryLeaksOnShutdown
    {$endif}
  {$else}
        False
  {$endif}
  );

In your options, RequireDebuggerPresenceForLeakReporting is defined. What's more, in the DLL, DebugHook is equal to 0, presumably because you are debugging the application rather than the DLL. This means that you call CheckBlocksOnShutdown passing False. And that False disables reporting of leaks.

You can resolve this by undefining RequireDebuggerPresenceForLeakReporting.