2016-10-16 1 views
3

ランタイム中に作成されたTIdHTTPオブジェクトがあります。IOHandlerおよびCompressionプロパティは、実行時にも作成されるオブジェクトに設定されています。私がTIdHTTPオブジェクトのFreeに電話すると、自動的にIOHandlerCompressionオブジェクトが割り当てられますか?TIdHTTP.Freeは、割り当てられたCompressorとIOHandlerもクリーンアップしますか?

アプリケーションの他の場所で
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; 

はコンプレッサーとIOHandlerのメモリリークで、この結果は、またはそれらが自動的に破棄されますか?

は、それが自動的に破壊されない念のため、私はこのようなのようDestroyメソッドのオーバーライドを追加しました:

答えて

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

    inherited; 
end; 

オブジェクトの寿命は、その所有者の寿命に接続されています。オブジェクトが解放された場合、オブジェクトはすべて解放されます。オブジェクトの作成時に所有者を渡さない場合は、不要になったオブジェクトを自分で解放する必要があります。

これは(あなたが所有者としてTIdHttpインスタンスを渡すため)IOHandlerは、あなたが所有者としてnilを渡すため(漏れた、と自由にないことにするあなたの具体的な例では、Compressorは、クライアントで解放されることを意味しますあなた自身)。両方の所有者としてResultを渡すと、デストラクタが廃止されます。また、「ちょうどの場合に」コードを書く習慣に慣れないでください。その振る舞いは決定論的なものなので、両方の方法を計画するのではなく、見つけようとしているかどうかわからない場合は

あなたが示したコードは、 Get-Request中に例外が発生した場合、TIdHttpインスタンス自体が(Compressorとともに)リークされます。実際には、Googleがリダイレクトを発行し、クライアントがこのリダイレクトを処理するように設定されていないため、コードをそのまま実行すると、これが発生します。あなたはそのようtry-finallyでコードをラップする必要があります

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

はまた、適切な例外処理をしたいが、私はあなたが簡潔さのためにそれを省いと仮定しています。

最後に、メモリリークの疑いがある場合、FullDebugModeで組み込みのFastMMを使用すると、シャットダウン時にすべてのメモリリークがレポートされ、記録されます。これはあなたがこの例ではメモリリークを発見するのに役立ちましたが、まだ考えていないリークについても一般に知らせることをお勧めします;)

+0

ありがとうございました。私はFastMMを調べます。私は実際のコードで例外処理を使用しますが、私はすぐに関連性があると思っていた部分にそれをトリミングしました。 –

+2

HTTPS URLにアクセスしている場合を除き、SSLlOHandlerを作成する必要はありません(例ではありません)。あなたがやっていてIndyの最新バージョンを使用しているなら、[SSLIOHandlerを作成する必要はありません](http://indyproject.org/Sockets/Blogs/ChangeLog/20141222.EN.aspx)その設定をカスタマイズする必要がある場合を除きます。 –

関連する問題