TIdHTTP.Free是否还清理了指定的Compressor和IOHandler?

时间:2016-10-16 14:07:25

标签: delphi

我在运行时创建了一个TIdHTTP对象,其IOHandlerCompression属性设置为在运行时也创建的对象。如果我在Free对象上拨打TIdHTTP,是否会自动释放分配给它的IOHandlerCompression个对象?

function CreateHTTP():TIdHTTP;
begin
  Result := TIdHTTP.Create(nil);
  Result.Compressor := TIdCompressorZLib.Create(Result)
  Result.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
end;

在应用程序的其他地方,这个代码被多次调用:

with CreateHTTP() do begin
  Data := Get('http://google.com');
  Free;
end;

这会导致Compressor和IOHandler的内存泄漏,还是会自动销毁?

万一它没有被自动销毁,我为Destroy方法添加了一个覆盖:

destructor TIdHTTP.Destroy;
begin
  if Assigned(Compressor) then
    Compressor.Free;
  if Assigned(IOHandler) then
    IOHandler.Free;

  inherited;
end;

1 个答案:

答案 0 :(得分:5)

对象的生命周期与其拥有者的生命周期有关;如果一个对象被释放,它将释放所有的孩子。如果您在创建对象时未传递所有者,则您有责任在不再需要该对象时自行释放该对象。

这意味着在您的特定示例中,Compressor将被客户端释放(因为您将TIdHttp实例作为所有者传递),而IOHandler将被泄露(因为你作为所有者传递零,并且不要自己释放)。将Result作为所有者传递给两者将使您的析构函数过时。此外,不要养成“以防万一”编写代码的习惯。这种行为是确定性的,所以如果你不知道它是否应该以某种方式找到答案,而不仅仅是计划两者;)

您展示的代码具有更大的潜在内存泄漏:如果在Get - 请求期间引发异常,则TIdHttp实例本身将被泄露(以及Compressor )。事实上,如果您按原样运行代码会发生这种情况,因为Google会发出重定向,并且客户端未设置为处理此重定向。您应该将代码包装在try-finally中,如下所示:

with CreateHTTP do begin
  try
    Get('http://google.com');
  finally
    Free;
  end;
end;

你也想做适当的异常处理,但我假设你为了简洁而把它留了下来。

最后,如果对内存泄漏有疑问,使用FullDebugMode中的内置FastMM将报告并记录关闭时的所有内存泄漏。这可以帮助你发现这个实例中的内存泄漏,但一般建议也要发现你还没有想到的泄漏;)