2011-02-14 3 views
4

私の質問はもともとディスクからロードされた文字列とメモリ不足のアプリケーションで処理されましたが、クラッシュさせる方法はずっと簡単です。以下のコードを実行すると、数秒で死ぬでしょう(iPad 4.2)。 理論的には、それは永遠に実行する必要があります。大規模なStringBuilderへの参照は保持されず、すぐにNULLに設定されます。 インストゥルメントで見ると、数回のループの後にメモリが160MBになり、アプリが死ぬでしょう。なぜメモリが解放されないのですか? 各ループは約10MBメモリを増加させます...このコードが「メモリ不足」のiOSアプリをクラッシュさせるのはなぜですか?

GCはちょうど追いつくことができませんが、Thread.Sleep()の遅延がどれほど大きいかは問題ではありません。

テストは学術的に見えるかもしれませんが、クラッシュしている実際のアプリに問題があります。 WebServiceリクエストから(巨大な)文字列を取得し、その文字列をXmlDocumentに変換して解析します(DBに何かを格納する)。その後、この方法は終了するが、メモリは高いままである。同じ方法をもう一度実行すると(1時間後に!)、アプリケーションはOOMで終了します。なぜメモリはまだ割り当てられていますか?

public override bool FinishedLaunching (UIApplication app, NSDictionary options) 
     { 
      Thread oThread = new Thread (DoIt); 
      oThread.Start (); 

      return true; 
     } 

     public void DoIt() 
     { 
      using(var o = new NSAutoreleasePool()) 
      { 
       while(true) 
       { 
        StringBuilder oSB = new StringBuilder(); 
        for(int i = 0; i < 800000; ++i) 
        { 
         oSB.Append("1234567890"); 
        } 
        oSB = null; 
        Thread.Sleep(1000); 
       } 
      } 
     } 

EDIT:私は、以下に示すように私は()メソッドを変更した場合、メモリが安定していることに気づきました。それはしばらくの間上昇し、次にGCが入り込んできれいになります。 NSStringオブジェクトを作成した後にs.Dispose()を追加すると、メモリがまったく上がることはありません。 これは.NET文字列クラスの問題であるようです。

public void DoIt() 
      { 
       using(var o = new NSAutoreleasePool()) 
       { 
           StringBuilder oSB = new StringBuilder(); 
        for(int i = 0; i < 800000; ++i) 
        { 
         oSB.Append("1234567890"); 
        } 
        while(true) 
        { 
          NSString s = new NSString(oSB.ToString()); 
         Thread.Sleep(1000); 
        } 
       } 
      } 

答えて

0

多分テキストがStringBuilderのは、内部で各反復で新しい大きな配列(これは、サイズが倍増される可能性があります)を割り当てメモリ

+0

私は質問を変更しました。圧縮解除とは関係ありません。 – Krumelur

1

に圧縮されていません。最終的に、断片化したヒープに終わるでしょう。

+0

しかし、私は連結する必要がある文字列を処理しなければならない正しい方法は何ですか?どういうわけかGCがヒープを最適化するように強制できますか?そして、それはなぜデバイス上でのみ起こりますが、シミュレータでは起こりませんか? – Krumelur

関連する問題