I have a TIdHTTP object created during runtime, which has its IOHandler and Compression properties set to objects that are also created during runtime. If I call Free on my TIdHTTP object, does this automatically free up the IOHandler and Compression objects assigned to it?
function CreateHTTP():TIdHTTP;
begin
Result := TIdHTTP.Create(nil);
Result.Compressor := TIdCompressorZLib.Create(Result)
Result.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
end;
Elsewhere in the application, this code gets called several times:
with CreateHTTP() do begin
Data := Get('http://google.com');
Free;
end;
Would this result in a memory leak of the Compressor and IOHandler, or are they automatically destroyed?
Just in case it is not automatically destroyed, I have added an override for the Destroy method like such:
destructor TIdHTTP.Destroy;
begin
if Assigned(Compressor) then
Compressor.Free;
if Assigned(IOHandler) then
IOHandler.Free;
inherited;
end;
The lifetime of an object is tied to the lifetime of its owner; if an object is freed, it will free all its children. If you do not pass an owner when creating an object, you are responsible for freeing the object yourself if it is no longer needed.
This means that in your specific example, the Compressor will be freed with the client (because you pass the TIdHttp instance as owner), while the IOHandler will be leaked (because you pass nil as owner, and don't free it yourself). Passing Result as owner to both will render your destructor obsolete. Also, don't get into the habit of writing code "just in case". The behavior is deterministic, so you if you don't know if it's one way or another you should strive to find out, instead of just planning for both ;)
The code you showed has a bigger potential memory leak though: If an exception is raised during the Get-Request, the TIdHttp instance itself will be leaked (along with the Compressor). In fact this does happen if you run the code as is, because Google issues a redirect, and the client is not set to handle this redirect. You should wrap the code in try-finally like so:
with CreateHTTP do begin
try
Get('http://google.com');
finally
Free;
end;
end;
You also want to do proper exception handling, but I'm assuming you left that out for brevity.
Finally, when in doubt about memory leaks, using the built-in FastMM in FullDebugMode will report and log all memory leaks on shutdown. This would have helped you spot the memory leak in this instance, but is advised in general to also spot the leaks you have not thought about yet ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With