为什么这段代码会破坏iOS应用程序的“内存不足”?

时间:2011-02-14 21:07:07

标签: xamarin.ios

我的问题最初处理的是从磁盘加载的字符串和我的应用程序内存耗尽,但有一种更简单的方法使它崩溃,我不明白为什么。运行下面的代码,它将在几秒钟内死亡(iPad 4.2)。 理论上它应该永远运行。没有对大型StringBuilder保留引用,它立即设置为NULL。 如果我在Instruments中观看它,几次循环后内存会上升到160MB,应用程序就会死掉。为什么内存没有发布? 每个循环增加内存大约10MB ......

有人认为GC无法跟上,但Thread.Sleep()的延迟有多大并不重要 - 最终,内存将消失。

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

2 个答案:

答案 0 :(得分:1)

StringBuilder在每次迭代时在内部分配新的更大的数组(它的大小可能会加倍)。最终,你最终会得到一个零碎的堆。

答案 1 :(得分:0)

也许文本在内存中未压缩