【问题标题】:Delphi Service Application TStringList LoadFromFile Memory LeakDelphi Service Application TStringList LoadFromFile 内存泄漏
【发布时间】:2014-11-18 04:47:45
【问题描述】:

那里有人可以解释为什么我的代码会导致 4KB 的内存泄漏,查看 TaskManager。 Delphi 2005,服务应用程序:

unit uMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
  ExtCtrls;

type
  TgwDebugService_s = class(TService)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceExecute(Sender: TService);
  private
    { Private declarations }
  public
    function GetServiceController: TServiceController; override;
    { Public declarations }
  end;

var
  gwDebugService_s: TgwDebugService_s;

implementation

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  gwDebugService_s.Controller(CtrlCode);
end;

function TgwDebugService_s.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

procedure TgwDebugService_s.ServiceExecute(Sender: TService);
begin
  // Service is Fired
  while not Terminated do
    ServiceThread.ProcessRequests(True);// wait for termination

end;

procedure TgwDebugService_s.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  // Service stops

end;

procedure TgwDebugService_s.Timer1Timer(Sender: TObject);
var
  sl : TStringList;
begin
  Timer1.Enabled := False;
  Sleep(1000);

  sl := TStringList.Create;
  try
    //if FileExists( 'c:\OnlyOnMyPc\test.txt' ) then
    sl.LoadFromFile( 'c:\OnlyOnMyPc\test.txt' );  // remove this line and will be find
    sl.Add( 'Test @ ' + FormatDateTime( 'dd.mm.yyyy hh:mm:ss.z', Now ) );
    sl.SaveToFile( 'c:\OnlyOnMyPc\test.txt' );
  finally
    sl.Clear;
    FreeAndNil( sl );
  end;

  Timer1.Enabled := True;

end;

end.

感谢您的时间和帮助。

干杯。 英镑

【问题讨论】:

  • 我没有在您的代码中看到任何内存泄漏,任务管理器不是合适的工具,请在完全调试模式下使用 FastMM。不过有几个改进点。 a) 不要实现 ServiceExecute,它已经开箱即用。 b) 不要使用 TStringList 在文件中添加一行,记住LoadFromFile 将整个文件读入内存,当日志文件变大时,这段代码会变得越来越慢(并且会占用内存)。在您的情况下,附加到带有TFileStream 的文件会更合适。
  • 为什么你的 Timer 事件中有Sleep();它是阻塞代码,首先使用 Timer 的原因之一是避免这种情况。另外,你不需要在销毁sl之前调用sl.Clear;销毁列表时会自动清除该列表。最后FreeAndNil 对局部变量来说是严重的过度杀伤; sl.Destroy 会很好。
  • @Craig 我认为 Free 会比 Destroy 更正常。这样您就可以避免在代码的某些部分(析构函数)中使用 Free 并在其他部分(方法)中使用 Destroy。
  • 因为@whosrdaddy 已经很伤心任务管理器不是监控内存泄漏的好工具。为什么?任务管理器显示某个应用程序分配了多少内存,但该特定应用程序实际上使用的内存可能比那个特定时间少得多。
  • @CraigYoung 显然我也知道。但你留下的评论并没有这么说。天真的开发者可能会开始在析构函数中调用Destroy,结果并不好。

标签: delphi memory-leaks tstringlist


【解决方案1】:

在寻找代码泄漏之前,您首先需要了解您是否真的有泄漏。任务管理器显示了 Windows 对您的应用程序的了解,它的数量需要在 Windows 如何管理内存的上下文中理解 - 然后您必须了解 Delphi 如何管理应用程序内的内存。

要了解如何阅读任务管理器编号,我建议您阅读出色的 Mark Russinovich 博客和视频:

http://channel9.msdn.com/Events/TechEd/NorthAmerica/2011/WCL405

他将向您解释 Windows 中内存分配的实际工作原理(Delphi 内存管理器然后对其进行子分配,但它仍然需要使用 Windows 内存分配调用),还将解释他的许多工具,这些工具可以让您更深入地了解Windows 应用程序的许多内部工作原理 - FastMM 无法告诉您。

还有一些称为“分析器”的工具可以跟踪内存分配和释放,并告诉您哪些代码分配了内存,然后又没有释放它。

否则你可能会追逐实际上不存在的泄漏......

【讨论】:

  • 这是一个答案,因为首先您需要了解您真正要问的是什么......如果您首先不了解泄漏是什么并使用错误/不完整,那么尝试跟踪泄漏是完全没用的信息来检查它。正如 Raymond Chen 经常解释的那样,有时你不需要回答别人的要求——你真的要了解他或她真正需要什么。在这种情况下,在查找代码泄漏之前,您需要向 OP 解释如何正确理解他或她是否有泄漏。
  • 应该是评论。并非所有问题都有答案。这是其中之一。
  • 它有一个答案:学习如何正确检查内存泄漏,然后再相信有一个并浪费时间询问某人如何解决可能一开始就不存在的泄漏。通过这种方式,您可以帮助某人专注于真正重要的事情,而在这种情况下评论 Free/FreeAndNil 的使用是毫无用处的。
  • 这里唯一的字面问题是那里(这里?)是否有人可以解释 4KB 泄漏。 “是的,Mark Russinovich 可以解释”可能会满足这个问题,具体取决于他是否那里
  • Russinovich 在视频中,将向您解释 4KB 的“泄漏”是什么。如果您懒得看它并了解 Windows 内存管理器的工作原理以及任务管理器真正向您展示的内容,并且更愿意成为通常无知的 Delphi 开发人员,他们总是想知道在其 IDE 之外会发生什么,因为除了在表单上放置控件他对 Windows 的真正工作原理一无所知,好吧,不客气……或者你可能会花一些时间了解 Windows,成为一个真正的 Windows 开发人员,而不仅仅是一个“组件投放器和事件”作家”。您的选择...
猜你喜欢
  • 2017-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
相关资源
最近更新 更多