-1

少し読んだ後、C# でコーディングするものはすべてマネージ コードであり、メモリ リークを引き起こすべきではないことがわかりました。それでも、私のプログラムは、ある種のメモリ リークを示唆するような動作をします。

私のプログラム全体は次のようになります:( 現在、実際のコードは持っていません)

while(true)
{
    //Source of the "leak"
    List<object> _objects = ReturnAllWindows(); 

    //Do something awesome with the list...

    System.Threading.Thread.Sleep(10);
}

ReturnAllWindowspinvokeを組み合わせて使用​​し、現在開いているすべてのウィンドウを取得するメソッドです。user32.dllEnumWindows

プログラムを実行すると、すぐにメモリが急上昇し、OutOfMemoryException.

EnumWindows私が読んだことから、私が考えることができる唯一のことは、関数に何らかのメモリリークがあるということですが、user32 が完全に管理されていないとはほとんど想像できません。

それで、何が起こっているのですか?どうすればそれを防止/回避できますか?


編集: 解決しました。問題は、このリストが後で適切に処理されなかったマルチスレッドと組み合わせて使用​​されることでした。この行にコメントを付けるReturnAllWindowsと、マルチスレッドに到達することはなく、プラットフォームの呼び出しはまったく問題ではありませんでした。

4

1 に答える 1

1

プラットフォームの呼び出し(つまり、マネージ コードからネイティブの非マネージ メソッドの呼び出し) である場合、メモリが何らかの形で完全に管理されていない可能性が非常に高くなります。ちょっと考えてみてください。ネイティブの非マネージド アプリケーションは、マネージド コードからの呼び出しをサポートする目的で作成されることはありません。したがって、オブジェクトは、下位レベルのシステム (開発された場合) によって制御されるか、制御されないアンマネージ メモリとして存在します。したがって、マネージ コードからネイティブ メソッドを呼び出すと、いわゆるボクシングが行われ、ネイティブ メモリをラップするマネージ オブジェクトが作成されます。

では、.NET にメモリ リークはありますか? 技術的には、いいえ。伝統的な意味ではありません。しかし、ゴミが存在するという考えは間違いなく真実です。そして、ボクシングを扱うことは、(より適切な用語がないため) GC をさらに混乱させるだけです。

ボックス化されたデータのリストの素晴らしい操作のどこかで、オブジェクトの逆参照が必要だと思います。たとえば、foreach を使用してデータのコレクションを繰り返し処理していて、各サイクルが完了した後にデータが不要になった場合は、そのデータへのマネージド参照をすべて削除する必要があります。たとえば、次の例を考えてみましょう。

List<object> foo = new List<object>(); // Imagine this is your list of data

foreach (var item in foo)
{
    // Execute an awesome expression here
}

一見無害に見えますが、これらの式はメモリを解放することはありません。メモリは常に何らかの方法で参照されているためです。これのメモリ最適化バージョンは次のようになります。

List<object> foo = new List<object>(); // Imagine this is your list of data

while (foo.Count > 0)
{
    var item = foo[0];

     // Execute an awesome expression here

     item = null;
     foo.RemoveAt(0);
}

2 番目の例では、リソースへの参照が残っておらず、ボックス化されたデータがコレクションの対象になっていることに注目してください。.NET のメモリの問題は追跡が非常に難しいことが多いため、これが完全な問題ではない可能性があります。おそらく、特定の問題をよりよく理解するために、アプリケーションのプロファイリングを検討してください。お役に立てれば。

于 2013-05-22T12:03:10.897 に答える