我有一个TIdHTTP在运行时期间创建的对象,它有IOHandler和Compression设置为在运行期间也创建的对象的属性.如果我把Free我的TIdHTTP对象,这是否会自动释放的IOHandler,并Compression分配给它的对象?
function CreateHTTP():TIdHTTP;
begin
Result := TIdHTTP.Create(nil);
Result.Compressor := TIdCompressorZLib.Create(Result)
Result.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
end;
Run Code Online (Sandbox Code Playgroud)
在应用程序的其他地方,这个代码被多次调用:
with CreateHTTP() do begin
Data := Get('http://google.com');
Free;
end;
Run Code Online (Sandbox Code Playgroud)
这会导致Compressor和IOHandler的内存泄漏,还是会自动销毁?
为了防万一它没有被自动销毁,我为这个Destroy方法添加了一个覆盖:
destructor TIdHTTP.Destroy;
begin
if Assigned(Compressor) then
Compressor.Free;
if Assigned(IOHandler) then
IOHandler.Free;
inherited;
end;
Run Code Online (Sandbox Code Playgroud)
对象的生命周期与其所有者的生命周期有关; 如果一个对象被释放,它将释放所有的孩子.如果在创建对象时未传递所有者,则您有责任在不再需要时自行释放该对象.
这意味着在您的特定示例中,Compressor将使用客户端释放(因为您将TIdHttp实例作为所有者传递),而IOHandler将泄露(因为您将nil作为所有者传递,并且不自行释放它).Result作为所有者传递给两者将使您的析构函数过时.此外,不要养成"以防万一"编写代码的习惯.这种行为是确定性的,所以如果你不知道它是否应该以某种方式努力找出,而不仅仅是计划两者;)
您显示的代码具有更大的潜在内存泄漏:如果在Get-Request 期间引发异常,则TIdHttp实例本身将被泄露(连同Compressor).实际上,如果您按原样运行代码会发生这种情况,因为Google会发出重定向,而客户端未设置为处理此重定向.您应该try-finally像这样包装代码:
with CreateHTTP do begin
try
Get('http://google.com');
finally
Free;
end;
end;
Run Code Online (Sandbox Code Playgroud)
你也想做适当的异常处理,但我假设你为了简洁而把它留了下来.
最后,当对内存泄漏有疑问时,使用FullDebugMode中的内置FastMM将报告并记录关闭时的所有内存泄漏.这可以帮助你发现这种情况下的内存泄漏,但一般建议也要发现你还没有想到的泄漏;)
| 归档时间: |
|
| 查看次数: |
236 次 |
| 最近记录: |