3

ユーザーがそれを使用した後、ユーザーはそれを「リセット」して再度使用できるアプリケーションを作成しています。実際の使用では、コントロールを含むいくつかのオブジェクトが作成されます。

Process Explorer を使用してメモリ使用量を確認したところ、アプリを使用するとメモリ使用量が増加しますが、アプリを「リセット」するとメモリ使用量はほとんど減少しません。

そのため、「リセット」時にDisposeすべてのControls を再帰的に削除し、GC.Collect();ブートに a を追加しました。しかし、Process Explorer -> (app's-) Properties -> .Net CLR Memoryまだヒープ上に多くのものが表示され、多くのメモリが使用されています。

これは(必然的に)メモリリークですか?そして、強制GCが役に立たないのはなぜですか?

編集:

デバッグのためだけに追加しましたGC.Collect();-リークがあるかどうかを判断するためです。GCが機能するまで「一時的なリーク」について心配していません.スコープから外れないオブジェクトがあるかどうか(まだ見つけていませんが)、またはそれが単なる問題であるかどうかを見つけようとしています.時間、およびメモリが再利用されます。

4

3 に答える 3

5

これは(必然的に)メモリリークですか?

はい、いいえ。ほとんどの場合、C# アプリで真のメモリ リークが発生することはありません。内部でネイティブ リソースを使用する型でさえ、Dispose() が呼び出されなかった場合、ファイナライザーでクリーンアップされます。

いずれにせよ、クリーンアップに時間がかかりすぎる古い参照やネイティブ リソース (または自分自身をリークする適切に記述されていないネイティブ関数) が存在する可能性があります。これは、アンマネージ言語で発生する真のメモリ リークと同じ実際的な結果をもたらします。

そして、強制GCが役に立たないのはなぜですか?

あなたは GC に提案をしましたが、GC はそれを採用しませんでした。GC.Collect()GC がすべてをクリーンアップすることを強制するわけではなく、ドキュメンテーションがそれを教えてくれます。第二に、このメモリ使用量は実際に問題を引き起こしていますか? どのくらいのメモリが消費されていますか? 解放されることはありますか?少量であれば、おそらく何も心配する必要はありません。GC に任せてください。

あなたのコードを見なくても、私にできることは推測することだけです。C# アプリでメモリ不足が発生する原因はいくつかあります。

  1. 古い参照。決して消去しない「死んだ」オブジェクトへの参照のリスト。イベント ハンドラーもこれを引き起こす可能性があります。たとえば、イベント デリゲートはサブスクライバーへの参照を保持しているため、静的イベントは常にサブスクライブ解除する必要があります。

    そのため、サブスクライバーがイベントのサブスクライブを解除せずにスコープ外に出ると、これらの「死んだ」オブジェクトへの有効な参照が常に存在するため、本質的にメモリ リークが発生します。親 (イベント パブリッシャー) は通常、必要なときにスコープ外になるため、イベントの一般的なユース ケースでは、これが発生しないことに注意してください。

  2. IDisposable を実装するオブジェクトを破棄しない。確かに、それらはおそらくファイナライザーで自分自身をクリーンアップします (すべての .NET IDisposable 型が行い、残りの型も行う必要があります) が、ファイナライザーは不確定なタイミングで実行されるため、全体が予測不能になります。Dispose() (using可能な場合はステートメントを使用) をできるだけ早く呼び出すようにしてください。

  3. 大きなオブジェクト ヒープの断片化。大量の「大きな」オブジェクト (85,000 バイトを超えるオブジェクト) を割り当てている場合、このメモリ セグメントが断片化される可能性があります。このメモリは、標準ヒープに割り当てられた第 0 世代および第 1 世代のオブジェクトほど頻繁にはクリーンアップされません。

.NET GC は複雑であり、通常は非常にうまく機能します。を呼び出すことが許容される場合もありGC.Collectますが、いつそれが良い考えなのかを理解する必要があります。たとえば、存続期間の短いオブジェクトを大量に作成する場合です。

他の手段を使い果たしたときに、RedGate の .NET メモリ プロファイラーを使用して良い経験をしました。ご存知のように、私は彼らのために働いていませんし、私は彼らと何らかの形で提携していません. 一見の価値あり。

于 2012-10-30T21:40:59.407 に答える
2

リークしているメモリを見つけるには、次のように設計されたツールを使用します。

.NETでメモリリークを見つけるのに役立つ戦略とツールは何ですか?

.NET Frameworkのガベージコレクターは、メモリの負荷がヒューリスティックを超えるまでメモリを解放しません。

于 2012-10-30T21:40:06.447 に答える
1

他の人が指摘しているGC.Collect()ように、GC を保証するものではありません。試すことができる 1 つのGetTotalMemory方法は、ブール値のパラメーターを使用して完全な GC を強制する方法です。

GC.GetTotalMemory(true);

これにより、全体のコレクションが強制的に実行され、割り当てられたマネージド メモリの量の概算がバイト単位で得られます。

示されている他の方法と同様に、これは収集が行われることを保証するものではなく( MSDN ドキュメントの備考セクションを参照)、とにかく収集できるのは明らかに適格なものだけです。

于 2012-10-30T21:45:22.530 に答える