MonoTouch不稳定性仍在继续:托管内存分配器崩溃

时间:2011-04-14 17:06:12

标签: ios4 iphone-sdk-3.0 xamarin.ios

长话短说:我可以分配大量非托管内存,但尝试在托管内存中分配相同数量(或更少)会导致GC_remap(下面的callstack)中的MonoTouch崩溃。

详细信息:

我将谈谈上面描述的行为的一个例子。我的应用程序偶尔分配一个2.5MB大小的托管内存(使用新的byte []),并且它经常在我的iPhone4上死掉,下面粘贴了callstack(即分配期间的mprotect错误)。我没有保留对这些2.5MB块的引用比单个函数调用更长的时间。

The MonoTouch guys say that 'mprotect errno 12' means you've exhausted memory on your device,但事实是,我的应用程序可以使用很多的内存。我可以在我的应用启动时分配 0MB 10MB 200MB 非托管内存(使用Marshal.AllocHGlobal) ,每一帧触摸它,它对我的​​应用程序的行为或此mprotect错误的频率没有区别。

一些注释

  • GC.TotalMemory告诉我,我的应用程序一直位于 3MB 5MB 的托管内存使用率之间。
  • 我的应用程序中有其他位置,我正在分配更大的非托管内存块,并且它永远不会在那里崩溃。我创建了压力测试,加载4MB(非托管)纹理数据,将其交给GL,并在每一帧绘制它,应用程序坚如磐石,直到我开始要求大块托管内存。 / LI>
  • GC.CollectionCount几乎没有变化,除非我自己调用GC.Collect。
  • MonoTouch 3.2.3以及MonoTouch 4.0也会出现同样的情况。
  • 我们所有的测试设备(iPhone 3G,3GS,4,iPad,iPad2)都会出现同样的情况。
  • 在发布版本和调试版本中也会发生相同的行为,尽管调试版本会更频繁地发生这种情况。

引发崩溃的方法

  • 如果我创建一个循环调用GC.Collect,然后休眠1ms,这会使崩溃更快发生(即,如果我在调试版本中,几乎立即发生)。
  • 使用某些.NET功能(如WebRequest)也会导致此崩溃。我只能假设它在那里的某个地方分配大块的托管内存。

崩溃的方式

有两种方法可以减少崩溃的频率或完全修复它:

  1. 如果我预先分配2.5 MB的托管内存,然后在应用程序的生命周期内保留它,那么就不会崩溃。
  2. 如果我在用它做任何事情之前把2.5MB大块的内存固定住,这似乎有帮助。
  3. 结论/问题

    由于此问题,我们尚未在我们的应用中实现完全稳定性。这个崩溃(总是在GC_remap中)发生在我们整个应用程序的随机分配中(我这里的2.5MB示例就是我选择隔离和重新编写的那个)。

    问题:

    1. 我根本不信任托管分配器吗?
    2. 为什么我可以分配 200MB 的非托管内存,但是当我要求 2.5MB 时,托管分配器会死掉? (注意:即使我没有分配200MB的非托管内存,当我要求2.5MB时也会死掉。)
    3. 为什么应用程序完全正常,如果我在应用程序的生命周期内占用2.5MB,但是如果我将它交还给系统(并调用GC.Collect)并再次要求2.5MB,那么崩溃更严重!如果这确实是一个内存不足的情况,那么给系统提供2.5MB的数据不应该比杀死它更好吗?
    4. 我们甚至可以使用MonoTouch吗?

      我的团队正在认真考虑放弃MonoTouch用于我们的产品,因为我们无法让它稳定可靠。

      我们也无法通过堆栈溢出,通过在Novell网站上提交错误或直接通过电子邮件发送MonoTouch的支持电子邮件来获取MonoTouch团队的时间。我们已将(托管和非托管)内存使用量减少到荒谬的低点,但由于此问题,应用程序仍然崩溃。

      在短期内,我想到的唯一解决方法是在启动时分配一大块内存(2-5MB),将其设为PIN,以便垃圾收集器永远不会触及它,并将自己的分配器编写到dole根据需要将此内存块的一部分输出到我的应用程序。但如果这是MonoTouch下可能的最佳解决方案,那么只要我能从MonoTouch获得逃逸速度,我就会想要我的钱。

      ...

      Mprotect failed at 0xaa00000 (length 3801088) with errno 12
      Stacktrace:
      
        at MyApp.GameScreen/VerifyPictureDialog.StoreBasePictureData () [0x00000] in /Users/dussault/s/MyApp/Main/Src/PhotoScreens.cs:428
        at MyApp.GameScreen/VerifyPictureDialog.ApplyFilters (bool) [0x0004b] in /Users/dussault/s/MyApp/Main/Src/PhotoScreens.cs:640
        at MyApp.GameScreen/VerifyPictureDialog.Simulate (single) [0x00077] in /Users/dussault/s/MyApp/Main/Src/PhotoScreens.cs:477
        at MyApp.BaseWindow.Simulate (single) [0x00007] in /Users/dussault/s/MyApp/Main/Src/BaseWindow.cs:56
        at MyApp.BaseWindow.Simulate (single) [0x00007] in /Users/dussault/s/MyApp/Main/Src/BaseWindow.cs:56
        at MyApp.GameScreen.Simulate (single) [0x00238] in /Users/dussault/s/MyApp/Main/Src/GameScreen.cs:3114
        at MyApp.BaseWindow.Simulate (single) [0x00007] in /Users/dussault/s/MyApp/Main/Src/BaseWindow.cs:56
        at MyApp.WindowMgr.Simulate (single) [0x0002f] in /Users/dussault/s/MyApp/Main/Src/WindowMgr.cs:126
        at MyApp.Game1.Update (Microsoft.Xna.Framework.GameTime) [0x0010f] in /Users/dussault/s/MyApp/Main/Src/Game1.cs:1194
        at Microsoft.Xna.Framework.Game.DispatchUpdate (Microsoft.Xna.Framework.GameTime) [0x00000] in /Users/dussault/s/MyApp/Main/Src/XNA-Emulation/GraphicsDevice.cs:531
        at MyApp_iOS.EAGLView.OnUpdateFrame () [0x00050] in /Users/dussault/s/MyApp/Main/Src/iOS/EAGLView.cs:310
        at MyApp_iOS.EAGLView.SimulateAndRender () [0x0000a] in /Users/dussault/s/MyApp/Main/Src/iOS/EAGLView.cs:279
        at MyApp_iOS.EAGLView.MainLoopTimerCallback () [0x00006] in /Users/dussault/s/MyApp/Main/Src/iOS/EAGLView.cs:231
        at MonoTouch.Foundation.NSActionDispatcher.Apply () <0x0002b>
        at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>
        at MonoTouch.UIKit.UIApplication.Main (string[],string,string) <0x000cf>
        at MonoTouch.UIKit.UIApplication.Main (string[]) <0x00023>
        at MyApp_iOS.Application.Main (string[]) [0x00000] in /Users/dussault/s/MyApp/Main/Src/iOS/Main.cs:57
        at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>
      
      Native stacktrace:
      
          0   MyApp_iOS                           0x00af1b48 mono_handle_native_sigsegv + 412
          1   MyApp_iOS                           0x00b1c66c sigabrt_signal_handler + 148
          2   libSystem.B.dylib                   0x33bd3ddf _sigtramp + 42
          3   libSystem.B.dylib                   0x33bd52cb kill + 10
          4   libSystem.B.dylib                   0x33bd52bd raise + 16
          5   libSystem.B.dylib                   0x33be9d79 abort + 56
          6   MyApp_iOS                           0x00c74378 GC_remap + 200
          7   MyApp_iOS                           0x00c62c04 GC_allochblk_nth + 1536
          8   MyApp_iOS                           0x00c625b4 GC_allochblk + 96
          9   MyApp_iOS                           0x00c6bf6c GC_alloc_large + 132
          10  MyApp_iOS                           0x00c6c5e8 GC_generic_malloc + 324
          11  MyApp_iOS                           0x00c6c8c8 GC_malloc_atomic + 332
          12  MyApp_iOS                           0x00bd8e88 mono_object_allocate_ptrfree + 64
          13  MyApp_iOS                           0x00bd8ff4 mono_array_new_specific + 148
          14  MyApp_iOS                           0x009173f4 wrapper_managed_to_native_object___icall_wrapper_mono_array_new_specific_intptr_int + 68
          15  MyApp_iOS                           0x002cd880 MyApp_GameScreen_VerifyPictureDialog_ApplyFilters_bool + 628
          16  MyApp_iOS                           0x002cbffc MyApp_GameScreen_VerifyPictureDialog_Simulate_single + 768
          17  MyApp_iOS                           0x002ef9d0 MyApp_BaseWindow_Simulate_single + 280
          18  MyApp_iOS                           0x002ef9d0 MyApp_BaseWindow_Simulate_single + 280
          19  MyApp_iOS                           0x002a71fc MyApp_GameScreen_Simulate_single + 2736
          20  MyApp_iOS                           0x002ef9d0 MyApp_BaseWindow_Simulate_single + 280
          21  MyApp_iOS                           0x0038068c MyApp_WindowMgr_Simulate_single + 376
          22  MyApp_iOS                           0x0027f798 MyApp_Game1_Update_Microsoft_Xna_Framework_GameTime + 1992
          23  MyApp_iOS                           0x0039afc8 Microsoft_Xna_Framework_Game_DispatchUpdate_Microsoft_Xna_Framework_GameTime + 148
          24  MyApp_iOS                           0x0026ec10 MyApp_iOS_EAGLView_OnUpdateFrame + 716
          25  MyApp_iOS                           0x0026e8cc MyApp_iOS_EAGLView_SimulateAndRender + 196
          26  MyApp_iOS                           0x0026e1cc MyApp_iOS_EAGLView_MainLoopTimerCallback + 296
          27  MyApp_iOS                           0x009a7dfc MonoTouch_Foundation_NSActionDispatcher_Apply + 44
          28  MyApp_iOS                           0x00912540 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 200
          29  MyApp_iOS                           0x00acc9c4 mono_jit_runtime_invoke + 2800
          30  MyApp_iOS                           0x00bd3ea4 mono_runtime_invoke + 140
          31  MyApp_iOS                           0x00c7d214 monotouch_trampoline + 2840
          32  Foundation                          0x3363b469 __NSFireTimer + 136
          33  CoreFoundation                      0x33a770a3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
          34  CoreFoundation                      0x33a76b5b __CFRunLoopDoTimer + 850
          35  CoreFoundation                      0x33a481b5 __CFRunLoopRun + 1088
          36  CoreFoundation                      0x33a47c87 CFRunLoopRunSpecific + 230
          37  CoreFoundation                      0x33a47b8f CFRunLoopRunInMode + 58
          38  GraphicsServices                    0x33b0e4ab GSEventRunModal + 114
          39  GraphicsServices                    0x33b0e557 GSEventRun + 62
          40  UIKit                               0x32099329 -[UIApplication _run] + 412
          41  UIKit                               0x32096e93 UIApplicationMain + 670
          42  MyApp_iOS                           0x009d484c wrapper_managed_to_native_MonoTouch_UIKit_UIApplication_UIApplicationMain_int_string___intptr_intptr + 240
          43  MyApp_iOS                           0x009b4c00 MonoTouch_UIKit_UIApplication_Main_string__ + 36
          44  MyApp_iOS                           0x00269694 MyApp_iOS_Application_Main_string__ + 128
          45  MyApp_iOS                           0x00912540 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 200
          46  MyApp_iOS                           0x00acc9c4 mono_jit_runtime_invoke + 2800
          47  MyApp_iOS                           0x00bd3ea4 mono_runtime_invoke + 140
          48  MyApp_iOS                           0x00bd6f3c mono_runtime_exec_main + 784
          49  MyApp_iOS                           0x00bd5f6c mono_runtime_run_main + 1048
          50  MyApp_iOS                           0x00ad7940 mono_jit_exec + 216
          51  MyApp_iOS                           0x00ac2e38 main + 3536
          52  MyApp_iOS                           0x000133a0 start + 52
      
      Debug info from gdb:
      
      
      =================================================================
      Got a SIGABRT while executing native code. This usually indicates
      a fatal error in the mono runtime or one of the native libraries
      used by your application.
      =================================================================
      

1 个答案:

答案 0 :(得分:1)

Darwin内核过度使用内存。

这意味着如果你要求200兆的ram,你就会得到它们,即使它们不可用,只要你没有消耗内存,你的应用程序就会运行细

只有当您实际写入页面时,才会将页面分配给您的流程。

正确的测试需要你分配内存,然后填满用过的内存,这就是为什么你可能会得到这样的印象,即使你甚至没有它也可以分配200兆的内存。

一个简单的程序会告诉你:尝试分配500兆,操作系统会说“是的,你得到它”,但是没有带有这种内存的iPhone。

示例测试案例将大大有助于显示问题所在。