8

メモリリークがあるように見える.NETアプリケーションに取り組んでいます。私は教科書の答えを知っています、イベントは購読をやめるべきであり、使い捨ての物は処分されるべきです...

エラーを再現できるテストハーネスがあります。あるクラスのファイナライザーでコンソールに書き込みます

public class Foo
{
   // Ctor
   public Foo()
   {
   }

   ~public Foo()
   {
       Console.WriteLine("Foo Finalized");
   }
}

テストハーネスでは、Fooの単一インスタンスを作成し(これにより、他の何百ものタイプが作成され、相互作用します)、それを削除してガベージコレクターを呼び出します。

Fooファイナライザーが呼び出されることはありません。私はこの設定で同様のクラスを持っており、これはコントロールテストとして完成します。

だから私の質問はこれです:

商用ツールまたはオープンソースツールを使用して、Fooへの参照を保持しているものを正確に判断するにはどうすればよいですか?

dotTrace Memory Profilerのプロフェッショナルライセンスを持っていますが、ヘルプファイルからその使用方法を理解できません。

更新:現在、dotMemory 4.0を使用しています。これは、(良いが使用できない)dotTraceMemory3.5の後継です。

4

5 に答える 5

6

SOSデバッガー拡張機能をご覧ください(無料で、Visual Studio内で使用できます)。

あなたはこれこれがstartetを取得するのに役立つと思うかもしれません。

SOSの設定に成功した場合(これは時々注意が必要です)、何が簡単なことへの参照を保持するかを知ることは

// load sos
.load sos
// list of all instances of YourTypeName in memory with their method tables
!DumpHeap -type YourTypeName  
// put here the method table displayed by the previous command
// it will show you the memory address of the object
!DumpHeap -mt 07f66b44              
// displays information about references the object at the specified address
!GCRoot 02d6ec94
于 2012-06-21T08:15:41.373 に答える
6

メモリリークのデバッグは非常に複雑なプロセスになる可能性があり、プログラムロジックと少なくともいくつかの.Net内部(特にガベージコレクタの動作)を完全に理解する必要があります。

詳細については、次のリンクを参照してください。

良い紹介

実践コース:

GCおよび.Net内部

SOS拡張機能を備えたWinDbg

幸運を!

于 2012-06-21T08:26:50.670 に答える
3

ファイナライザーは決定論的に呼び出されないため、信頼できる方法で物事を追跡するためにファイナライザーを使用することに注意してください。ファイナライザーを削除して代わりにを使用するとWeakReference<Foo>、オブジェクトが収集されたかどうかを判断できるはずです。

すべてのメモリプロファイラは、このような問題を見つけることができるはずですが、難易度はさまざまです。私は個人的にANTSを使用しました。これは非常に使いやすいですが、無料ではありません。これは、GCルートオブジェクトからずっと、Fooインスタンスへの参照図を表示するのに役立ちます。この図を見ると、通常、誰が参照を保持しているかを簡単に見つけることができます。

于 2012-06-21T07:59:58.527 に答える
2

メモリプロファイラーを使用して、メモリリークを特定できます。ここにあるいくつかの、

MemProfiler

ANTSプロファイラー

于 2012-06-21T07:55:11.937 に答える
1

まず、ファイナライザーを使用しないでください。理由は次のとおりです。

ファイナライズ操作には、次の制限があります。

  • ガベージコレクション中にファイナライザーが実行される正確な時刻は未定義です。CloseメソッドまたはDisposeメソッドを呼び出さない限り、リソースが特定の時間に解放されることは保証されません。

  • 2つのオブジェクトのファイナライザーは、一方のオブジェクトがもう一方のオブジェクトを参照している場合でも、特定の順序で実行されることが保証されていません。つまり、オブジェクトAにオブジェクトBへの参照があり、両方にファイナライザーがある場合、オブジェクトAのファイナライザーの開始時にオブジェクトBがすでにファイナライズされている可能性があります。

  • ファイナライザーが実行されるスレッドは指定されていません。

引用元:http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx
代わりにDisposeメソッドを使用することをお勧めします。

第二に、メモリプロファイラーはそれらの参照を保持するものを見つけることができるはずです。個人的に私はANTSProfilerを使用していました。これは非常に優れたツールであり、非常に豊富なドキュメントがあります。次のドキュメントを読んでみてください。http://downloads.red-gate.com/HelpPDF/ANTS_Memory_Profiler/InstanceCategorizer.pdf インスタンスカテゴライザーは、オブジェクトのセットからGCルートへの参照のチェーンを表示します。

于 2012-06-21T08:17:03.703 に答える