2011-03-24 72 views
3

运行下面的代码时,应用程序在下面的堆栈跟踪中崩溃(约30秒后)。我觉得这很奇怪,因为我期望垃圾收集器清理这个内存。我们的应用程序有一个类似的模式,并与类似的堆栈跟踪崩溃。实例化NSObject导致内存不足崩溃

注释掉实例化NSObject成员的行使应用程序运行时不会崩溃。将实例化字节数组的行注释掉会使应用运行更长时间,但仍然崩溃。

乐器报告一个非常好的恒定实时字节为应用程序和仪器会导致应用程序运行更长时间没有崩溃,但它仍然崩溃(大约10分钟后)。不断的Live Bytes让我感觉垃圾收集器正在工作。

代码:

using System.Threading; 
using MonoTouch.Foundation; 
using MonoTouch.UIKit; 

namespace MyExample 
{ 
    public class Application 
    { 
     static void Main (string[] args) 
     { 
      UIApplication.Main(args); 
     } 
    } 

    public partial class AppDelegate : UIApplicationDelegate 
    { 
     public override bool FinishedLaunching (UIApplication app, NSDictionary options) 
     { 
      Thread testThread = new Thread(BreakMe); 
      testThread.Start(); 

      window.MakeKeyAndVisible(); 
      return true; 
     } 

     private void BreakMe() 
     { 
      while(true) 
      { 
       using (var arPool = new NSAutoreleasePool()) 
       { 
        MyGarbage garbage = new MyGarbage(); 
       } 
      } 
     } 

     private class MyGarbage 
     { 
      byte[] _Foo = new byte[100000]; 
      NSObject _Bar = new NSObject(); 
     } 
    } 
} 

应用程序输出:

Mprotect failed at 0x493c000 (length 4096) with errno 12 
Stacktrace: 

    at (wrapper managed-to-native) System.Array.CreateInstanceImpl (System.Type,int[],int[]) <0xffffffff> 
    at System.Array.CreateInstance (System.Type,int[]) <0x000bc> 
    at System.Array.CreateInstance (System.Type,int) <0x00057> 
    at System.MonoCustomAttrs.GetCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type,bool) <0x000db> 
    at System.MonoCustomAttrs.GetCustomAttribute (System.Reflection.ICustomAttributeProvider,System.Type,bool) <0x00033> 
    at System.Attribute.GetCustomAttribute (System.Reflection.MemberInfo,System.Type,bool) <0x0003f> 
    at MonoTouch.ObjCRuntime.Class.GetHandle (System.Type) <0x00037> 
    at MonoTouch.Foundation.NSObject.AllocIfNeeded() <0x00063> 
    at MonoTouch.Foundation.NSObject..ctor (MonoTouch.Foundation.NSObjectFlag) <0x00027> 
    at MonoTouch.Foundation.NSAutoreleasePool..ctor() <0x00037> 
    at MyExample.AppDelegate.BreakMe() [0x00000] in Main.cs:30 
    at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0x000cb> 

Native stacktrace: 

    0 MyExample      0x002db308 mono_handle_native_sigsegv + 404 
    1 MyExample      0x002fa5dc sigabrt_signal_handler + 148 
    2 libsystem_c.dylib     0x369c972f _sigtramp + 42 
    3 libsystem_c.dylib     0x369be3bb pthread_kill + 58 
    4 libsystem_c.dylib     0x369b6bff abort + 78 
    5 MyExample      0x0041e484 GC_remap + 200 
    6 MyExample      0x00411ee4 GC_allochblk_nth + 1536 
    7 MyExample      0x00411894 GC_allochblk + 96 
    8 MyExample      0x0041d94c GC_new_hblk + 116 
    9 MyExample      0x00413c3c GC_allocobj + 188 
    10 MyExample      0x0041859c GC_generic_malloc_inner + 352 
    11 MyExample      0x004187ac GC_generic_malloc + 132 
    12 MyExample      0x00418c60 GC_malloc + 208 
    13 MyExample      0x003a67dc mono_object_allocate + 64 
    14 MyExample      0x003a7240 mono_array_new_full + 828 
    15 MyExample      0x00341324 ves_icall_System_Array_CreateInstanceImpl + 896 
    16 MyExample      0x0012cf3c (wrapper managed-to-native) System.Array:CreateInstanceImpl (System.Type,int[],int[]) + 80 
    17 MyExample      0x0012d23c System.Array:CreateInstance (System.Type,int) + 88 
    18 MyExample      0x0018b70c System.MonoCustomAttrs:GetCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type,bool) + 220 
    19 MyExample      0x0018b560 System.MonoCustomAttrs:GetCustomAttribute (System.Reflection.ICustomAttributeProvider,System.Type,bool) + 52 
    20 MyExample      0x00131fd0 System.Attribute:GetCustomAttribute (System.Reflection.MemberInfo,System.Type,bool) + 64 
    21 MyExample      0x000795ec MonoTouch.ObjCRuntime.Class:GetHandle (System.Type) + 56 
    22 MyExample      0x00077e60 MonoTouch.Foundation.NSObject:AllocIfNeeded() + 100 
    23 MyExample      0x0007779c MonoTouch.Foundation.NSObject:.ctor (MonoTouch.Foundation.NSObjectFlag) + 40 
    24 MyExample      0x00074d10 MonoTouch.Foundation.NSAutoreleasePool:.ctor() + 56 
    25 MyExample      0x00002c34 MyExample.AppDelegate:BreakMe() + 164 
    26 MyExample      0x001f3e3c (wrapper runtime-invoke) object:runtime_invoke_dynamic (intptr,intptr,intptr,intptr) + 204 
    27 MyExample      0x002c4658 mono_jit_runtime_invoke + 3032 
    28 MyExample      0x003a34a8 mono_runtime_invoke + 140 
    29 MyExample      0x003a48f0 mono_runtime_delegate_invoke + 136 
    30 MyExample      0x003cb31c start_wrapper + 752 
    31 MyExample      0x003f09a0 thread_start_routine + 240 
    32 MyExample      0x0041f9ac GC_start_routine + 132 
    33 libsystem_c.dylib     0x369be311 _pthread_start + 248 
    34 libsystem_c.dylib     0x369bfbbc start_wqthread + 0 
+0

刚刚测试了相同的确切代码,它不会崩溃。但是,在线程中应用** NSAutoreleasePool ** **一次**。然后在'using'块中输入'while'代码。 – 2011-03-25 08:20:13

+0

我应该认定它不会在iPad模拟器中崩溃,并且我正在使用iOS 4.3的iPad 1上运行。 – tohlsen 2011-03-25 12:59:49

+0

@Dimitris是对的,你的代码有缺陷:没有使用声明,可能需要NSAutoreleasePool。进行修改,看看它是否解决了你的问题。模拟器与设备有很大不同,因为它可以访问更多的RAM,更快的CPU等。设备上的内存问题会更快发生。 – jonathanpeppers 2011-03-25 13:02:41

回答

2

对此的真实答案是,怀疑是Why is our MonoTouch app breaking in the garbage collector? It is not out of memory问题,这是内存管理器问题。堆栈跟踪对我来说非常熟悉。

+0

当MonoTouch本身出现问题时,我们花了几周的时间试图弄清楚这一点(认为是我们使用MonoTouch不正确),我感到非常沮丧。 而且我也很沮丧,它让Novell外部的人在他们自己的源代码中指出问题所在。抱歉发泄,但我希望这个笔记将听到MonoTouch NEEDS支持他们的平台(不仅仅是一个论坛)。 – tohlsen 2011-05-12 15:37:21

+0

今天运行测试来验证这实际上是我们遇到的问题。使用MonoTouch 3.x,即使在我们的代码中注入GC.Collect(并且杀死了性能)后,我们仍然遇到稳定性问题。我已经拿出来并升级到MonoTouch 4.0.3。更多关于明天的结果...... – tohlsen 2011-05-12 15:38:02

+0

可以说,我们深入了解了这一点,包括MonoTouch bug数据库和其他报告。一旦我们能够给他一个可重现的失败,杰夫就非常好,即使它需要几个小时才能发生。如果它是稳定的,请随时接受我的回答。 8-) – mj2008 2011-05-12 16:24:39

1

你已经把分配器与垃圾收集赛跑。如果您对演示进行简单更改并添加:

System.GC.Collect(); 

在循环中,您将看到它不再崩溃。

这里发生了什么是你正在尽可能快地分配。当GC耗尽内存时,它将扩展堆并收集。接下来的几次循环运行时间更长,然后由于堆积较大而再次收集,但最终比赛丢失。

在我放弃之前,对上述的小修改进行了10分钟的测试。

+0

非常感谢您给出答案,但解释原因。好的工作,再次,谢谢! – tohlsen 2011-03-28 13:13:49

+0

为什么分配器运行不足时,MonoTouch无法在分配器内部运行垃圾回收?看起来好像没有这样做,唯一确保它不会在分配中崩溃的方法是在每次分配之前调用GC.Collect。我在商店上有一个应用程序,即使经常分配的内存大致相同,但即使它在保持引用的对象方面表现良好(即它经常引用大致相同的内存量),也会受到随机GC_remap崩溃困扰。 – Mike 2011-04-09 00:55:23

+0

它的确如此,但还有其他一些因素在起作用。最终队列中有多少个对象?终结者有时间跑?等等。 – 2011-04-09 19:32:20