delphi 使用控制台应用程序报告关闭时的内存泄漏

0x6upsns  于 2022-11-04  发布在  其他
关注(0)|答案(4)|浏览(267)

我已经创建了一个控制台应用程序,并设置了ReportMemoryLeaksOnShutdown:= True。
我创建了一个TStringList,但没有释放它。
当程序完成执行时,我看到内存泄漏一小会儿,但随后控制台关闭。
我尝试过添加ReadLn;到最后,但当我这样做时,它只显示一个空白的控制台窗口,这是有意义的。
我需要找到一种方法,在内存泄漏报告之后,但在程序完全关闭之前暂停执行。
我用的是 Delphi 10西雅图。

program Project1;

{$APPTYPE CONSOLE}

uses
  System.Classes,
  System.SysUtils;

var
  s : TStringList;

begin
  try
    ReportMemoryLeaksOnShutdown := True;
    s := TStringList.Create;

    //ReadLn doesn't work here, which makes sense.
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  //I need to be able to pause the program somewhere after the end statement here.
end.
gj3fmq9x

gj3fmq9x1#

最简单的方法是在以前打开的命令窗口中运行应用程序。
如果您坚持要在IDE中运行时查看内存泄漏报告,请执行以下操作:

  • 在www.example.com中找到ShowMessage过程GetMem.inc( Delphi 10西雅图中的第4856行)
  • 在该程序的end;上放置中断点。

或者,如Sertac Akyuz所述,在system单元的end.上放置一个断点。
您也可以将内存泄漏报告重定向到文件。请从以下网址下载完整版本的FastMM
https://sourceforge.net/projects/fastmm/
或者更好,感谢Arioch 'The,从这里:
https://github.com/pleriche/FastMM4
并在FastMM4Options.inc中设置所需的选项

qeeaahzv

qeeaahzv2#

这是最近的 Delphi 版本中的一个bug。我刚刚在最近的免费Delphi 10.1 Starter中检查了它,它的行为就像你描述的那样-但由于它没有提供RTL源代码,我无法检查确切的原因。
在 Delphi XE 2中,其行为符合预期:创建任务模式对话框并等待您作出React,就像Sertak所描述的那样。
在 Delphi 10.1中,漏洞确实会报告给控制台窗口,但程序不会停止等待用户注意。这是一个糟糕的解决方案,因为这一原因和可能在脚本中使用控制台程序(CMD或PS脚本不会“理解”此消息,可能会将其与合法输出混淆,并导致后续阶段程序的执行失败。
我认为你必须在 Delphi 10.0上打开回归类型的bug报告--但是我不认为他们会在10.2发布之前修复它。
我还将您的应用程序从Delphi分叉内存管理器切换到了原始的内存管理器,然后恢复了错误的行为:程序显示消息框并等待直到我关闭它才退出IDE。
目前我建议你使用原来提到的内存管理器,而不是它的 Delphi 叉。

program Project1;

{$APPTYPE CONSOLE}

uses
  FastMM4,
  System.Classes,
  System.SysUtils;
...

原始内存管理器位于http://github.com/pleriche/FastMM4您可以在 Delphi 中使用Git客户端或独立的客户端来保持更新,或者您可以下载代码一次并停止更新,这取决于您。
其代码的相关引用如下:

{$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;

{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;

这段代码依赖于在桌面Windows上运行,所以Embarcadero可能试图“修复”它,使其跨平台。
也可以考虑添加其他形式的日志--到文件和/或到Windows Debug String中。它们不会像模态窗口那样引人注目,但至少可以帮助你保存信息,如果你知道在哪里可以找到它的话。

dsekswqp

dsekswqp3#

var
  SaveExitProcessProc: procedure;
  s: TStringList;

procedure MyExitProcessProc;
begin
  ExitProcessProc := SaveExitProcessProc;
  readln;
end;

begin
  SaveExitProcessProc := ExitProcessProc;
  ExitProcessProc := MyExitProcessProc;
  ReportMemoryLeaksOnShutdown := True;
  s := TStringList.Create;
end.
qpgpyjmq

qpgpyjmq4#

这当然是一个黑客,不要在生产中使用:)

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

但是,它会导致泄漏消息(和一些其他消息)显示在消息框中(按Ctrl+C可以复制所有文本)。

  • (使用 Delphi 10.2进行测试,请报告我们不希望出现的任何副作用)*

相关问题