私の質問はもともとディスクからロードされた文字列とメモリ不足のアプリケーションで処理されましたが、クラッシュさせる方法はずっと簡単です。以下のコードを実行すると、数秒で死ぬでしょう(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);
}
}
}
私は質問を変更しました。圧縮解除とは関係ありません。 – Krumelur