2011-03-24 30 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