2012-02-19 18 views
3

私はアプリケーションで大量のメモリリークを追跡しており、問題はMemoryStreamクラスと思われます。私が「使用する」キーワードまたは明示的な閉じる/破棄のいずれかを使用するときはいつでも、メモリはガベージコレクタによって決して収集されません。ここで何が間違っていますか?C#メモリリークメモリ、廃棄後/閉じる/ etc?

byte[] bData = System.IO.File.ReadAllBytes("F:\\application_exit_bw.png"); 
using(System.IO.MemoryStream hMemoryStreamOutput = new System.IO.MemoryStream()) 
{ 
    for (int i = 0; i < 10000; i++) hMemoryStreamOutput.Write(bData, 0, bData.Length); 
} 
Thread.Sleep(Timeout.Infinite); 

明示的にクローズ/ディープにすると、動作は変わりません。メモリが占​​有されており、アプリケーションを閉じるまで、またはアプリケーションがシステムメモリをすべて占有するまでその状態を維持します。助けて?

答えて

1

もう一つの問題は、「メモリリーク」を判断することです。測定するためにさまざまな方法があり、「無料」のメモリと、あなたが得ることができ、それに応じてtottaly異なる結果は、タスクマネージャで

  • メモリ使用量ショーは - 。すべてのメモリを考慮した場合でも下がる可能性は低い 『CLRによって』フリー。によるGCがメモリを使用しています
  • GCメモリのパフォーマンスカウンタ(およびプロパティ)の方法にGC - これらのものは、実際にメモリ上のGCのビューが表示されますあなたが管理するメモリリークを検出するためにそれらを使用したい

があります。 MemoryStream(および他の大きな86K +の割り当て)を使用するもう1つのもの - フルGでのみ収集されるラージオブジェクトヒープを使用しますCを起動すると、GC.Collectを2回実行する必要があります。アプリケーションの通常の流れでは十分に起こりますので、アプリケーションをシャットダウンする前にこのメモリが解放されることはありません。診断するには - GCコレクションのパーパスカウンター(GCの数)をチェックします。

もう1つ:「メモリ不足」例外が発生したためにメモリリークを解決しようとすると、アドレス空間の断片化(通常は32ビットプロセスのみ)が原因である可能性があります。その場合は、メモリを単一のチャンクに割り当てずにストリームを拡張するときにコピーする必要がある独自のメモリストリームを作成することを検討してください。または少なくともストリームのスペースを事前に割り当てようとします。

4

これは、非確定的なGCの症状です。 GCは、のメモリが解放される時点で保証するものではありません。これは通常の、期待された動作です。

GC.Collect()を呼び出して問題が解決するかどうかを確認してください。また、リリースモードで実行する必要があります。これは、デバッグモードでは、ローカル変数の存続期間が、あるポイントの後で使用されなくてもメソッドの終わりまで延長されるためです。

+2

+1、感謝 –

+0

いただきましたためdownvote?何か不正確ですか?エラーを報告してください、私は修正します! – usr

7

MemoryStreamクラスまたはサンプルコード内の使用方法に問題はありません。 .NetのGCは、それがなくなった直後にメモリをクリーンアップしません。代わりに、ヒープ内の空き領域が特定のしきい値に達したとき、またはGC.Collect呼び出しで明示的に呼び出されたときに、それを再要求します。

このシナリオでは、メモリが解放される唯一の方法は、using文の直後で、Thread.Sleepコールの前にGCが発生した場合です。これは起こりそうにないので、プログラムをプロファイリングすると、実際に漏れていないときにメモリリークのように見えるでしょう。

0

私はGC.Collectを呼び出すバッチ処理

static byte[] buffer; 

    public static object Read(XmlDocument xmlDocument) 
    { 
     if (buffer == null) 
     { 
      buffer = new byte[1024 * 1024 * 512]; 
     } 

     if (xmlDocument != null) 
     { 
      using (MemoryStream ms = new MemoryStream(buffer)) 
      { 
       xmlDocument.Save(ms); 
       ms.Flush(); 
       ms.Seek(0, SeekOrigin.Begin); 

       object result = ReadFromStream(ms); 

       ms.Close(); 
       return result; 
      } 
     } 
     else 
     { 
      return null; 
     } 
    } 
0

ため、この方法を使用している()良い習慣ではなく、解決策として使用すべきではありません。

デバッグモードチップ用 あなたは試してみて、それが何かを変更しますが、意図的なGC.Collect()の呼び出しに依存していないかどうかを確認することができます

...

関連する問題