2011-02-14 50 views
4

我的问题最初涉及从磁盘加载的字符串,而我的应用程序内存不足,但有一种更简单的方法使其崩溃,我不明白为什么。运行下面的代码,它会在几秒钟内死亡(iPad 4.2)。理论上它应该永远运行。大型StringBuilder没有引用,它立即被设置为NULL。 如果我在乐器中观看它,几次循环后内存将高达160MB,应用程序将会死亡。为什么没有释放内存? 每个循环增加了大约10MB的内存......这段代码为什么会崩溃iOS应用程序和“内存不足”?

一个想法是GC不能跟上,但无论Thread.Sleep()的延迟有多大 - 最终内存都将消失。

该测试可能看起来很流行,但我遇到了一个真正崩溃的应用程序的问题。它有一个从WebService请求中获取(巨大)字符串的方法,将该字符串转换为XmlDocument并解析它(将某些内容存储到数据库)。然后该方法退出但内存保持高。如果我再次执行相同的方法(一个小时左右!),该应用程序会死亡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); 
       } 
      } 
     } 

编辑:我注意到,如果我改变DO()方法如下所示,内存保持稳定。它上升一段时间,然后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

说不定文本是在存储器

+0

我改变了问题。它与解压缩无关。 – Krumelur

1

StringBuilder的每次迭代(它可能在尺寸上增加一倍)在内部分配新的更大的阵列解压缩。最终,你最终会得到一个碎片堆。

+0

但是当我需要处理需要连接的字符串时,那么正确的方法是什么?我可以以某种方式迫使GC碎片整理堆?为什么它只发生在设备上,而不是在模拟器中? – Krumelur