Reporting memory leaks on shutdown with a console application

前端 未结 4 600
野的像风
野的像风 2021-01-11 21:56

I\'ve created a console application and set ReportMemoryLeaksOnShutdown := True.

I\'ve created a TStringList but did not free it.

When the program finishes

相关标签:
4条回答
  • 2021-01-11 22:19

    The easiest is to simply run the application in a previously opened command window.

    If you insist on seeing the memory leak report while running in the IDE, do as follows:

    • Locate the ShowMessage procedure in GetMem.inc (line 4856 in Delphi 10 Seattle)
    • Place a breakpoint on the end; of that procedure.

    Alternatively, as Sertac Akyuz commented, put a break point on the end. of the system unit.

    You can also redirect the memory leak report to a file. Download the full version of FastMM from

    https://sourceforge.net/projects/fastmm/

    or better, thanks to Arioch 'The, from here:

    https://github.com/pleriche/FastMM4

    and set the needed options in FastMM4Options.inc

    0 讨论(0)
  • 2021-01-11 22:25
    var
      SaveExitProcessProc: procedure;
      s: TStringList;
    
    procedure MyExitProcessProc;
    begin
      ExitProcessProc := SaveExitProcessProc;
      readln;
    end;
    
    begin
      SaveExitProcessProc := ExitProcessProc;
      ExitProcessProc := MyExitProcessProc;
      ReportMemoryLeaksOnShutdown := True;
      s := TStringList.Create;
    end.
    
    0 讨论(0)
  • 2021-01-11 22:26

    That is a bug in recent Delphi versions. I just checked it in that recent free Delphi 10.1 Starter and it behaves as you describe - but as it provides no RTL sources I can not check the exact reason.

    In Delphi XE2 it behaves as expected: creates the task-modal dialog and waits for you to react, just like described by Sertak.

    In Delphi 10.1 the leak is indeed reported to the console window, but the program is not stopped to wait for user attention. That is poor solution, for both this reason and for the possible use of console programs in scripting (CMD or PS scripts would not "understand" this message and might confuse it with legitimate output and fail execution of further stages programs.

    I think you have to open regression-type bug report over Delphi 10.0 - but I do not think they would fix it until 10.2 release.

    I also switched your application from Delphi-forked memory manager to the original one, and then the erroneous behavior was reverted: the program displayed the message box and waited until I dismiss it before exiting into IDE.

    Currently i suggest you to use the mentioned original memory manager rather than Delphi fork of it.

    program Project1;
    
    {$APPTYPE CONSOLE}
    
    uses
      FastMM4,
      System.Classes,
      System.SysUtils;
    ...
    

    The original memory manager resides at http://github.com/pleriche/FastMM4 You can use Git client in your Delphi or a standalone one to keep yourself updated, or you can download the code once and stop updating, up to you.

    The relevant quotes of its code are:

      {$ifdef LogErrorsToFile}
         {Set the message footer}
          LMsgPtr := AppendStringToBuffer(LeakMessageFooter, LMsgPtr, Length(LeakMessageFooter));
          {Append the message to the memory errors file}
          AppendEventLog(@LLeakMessage[0], UIntPtr(LMsgPtr) - UIntPtr(@LLeakMessage[1]));
      {$else}
          {Set the message footer}
          AppendStringToBuffer(LeakMessageFooter, LMsgPtr, Length(LeakMessageFooter));
      {$endif}
      {$ifdef UseOutputDebugString}
          OutputDebugStringA(LLeakMessage);
      {$endif}
      {$ifndef NoMessageBoxes}
          {Show the message}
          AppendStringToModuleName(LeakMessageTitle, LMessageTitleBuffer);
          ShowMessageBox(LLeakMessage, LMessageTitleBuffer);
      {$endif}
        end;
      end;
    {$endif}
    end;
    

    and

    {Shows a message box if the program is not showing one already.}
    procedure ShowMessageBox(AText, ACaption: PAnsiChar);
    begin
      if (not ShowingMessageBox) and (not SuppressMessageBoxes) then
      begin
        ShowingMessageBox := True;
        MessageBoxA(0, AText, ACaption,
          MB_OK or MB_ICONERROR or MB_TASKMODAL or MB_DEFAULT_DESKTOP_ONLY);
        ShowingMessageBox := False;
      end;
    end;
    

    This code depends upon being run on desktop Windows, so maybe Embarcadero tried to "fix" it to make it cross-platform. However the way they did it broken it on Windows console....

    Also consider using adding other forms of logging - into the file and/or into the Windows Debug Strings. They would not be so attention-catching as the modal window, but would at least help you save the information, if you would know where to look for it.

    0 讨论(0)
  • 2021-01-11 22:38

    This is certainly a hack, don't use in production :)

    ReportMemoryLeaksOnShutdown:= True;
    IsConsole:= False;
    TStringList.Create;
    

    However, it causes the leak message (and some other messages) to be displayed in a message box (where all text can be copied by pressing Ctrl+C).

    (Tested with Delphi 10.2, please report any side effects we wouldn't like)

    0 讨论(0)
提交回复
热议问题