细节:
我将谈谈上面描述的行为的一个例子.我的应用程序偶尔分配一个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,并在每一帧绘制它,应用程序坚如磐石,直到我开始要求大块的托管内存.
> GC.CollectionCount几乎没有变化,除非我自己调用GC.Collect.
> MonoTouch 3.2.3以及MonoTouch 4.0也会出现同样的情况.
>我们所有的测试设备(iPhone 3G,3GS,4,iPad,iPad2)都会出现同样的情况.
>在发布版本和调试版本中也会发生相同的行为,尽管调试版本会更频繁地发生.
引发崩溃的方法
>如果我创建一个循环调用GC.Collect,然后休眠1ms,这会使崩溃更快发生(即,如果我在调试版本中,几乎立即).
>使用某些.NET功能(如WebRequest)也会导致此崩溃.我只能假设它在那里的某个地方分配大块的托管内存.
崩溃的方式
有两种方法可以减少崩溃的频率或完全修复它:
>如果我预先分配2.5 MB的托管内存,然后在应用程序的生命周期内保留它,那么就不会崩溃.
>如果我在用它做任何事情之前将2.5MB大块的内存固定,这似乎有所帮助.
结论/问题
由于这个问题,我们尚未在我们的应用程序中实现完全稳定性.这个崩溃(总是在GC_remap内部)发生在整个app中的随机分配中(我在这里的2.5MB示例就是我选择隔离和重新编写的那个).
问题:
>我完全不相信托管分配器吗?
>为什么我可以分配200MB的非托管内存,但是当我要求2.5MB时,托管分配器会死掉? (注意:即使我没有分配200MB的非托管内存,当我要求2.5MB时也会死掉).
>为什么应用程序完全正常,如果我在应用程序的生命周期内占用2.5MB,但是如果我将其交还给系统(并调用GC.Collect)并要求另外2.5MB以后,则崩溃是更差!如果这确实是一个内存不足的情况,那么给系统提供2.5MB的数据不应该比杀死它更好吗?
我们甚至可以使用MonoTouch吗?
我的团队正在认真考虑放弃MonoTouch用于我们的产品,因为我们无法让它稳定可靠.
我们也无法从MonoTouch团队获得堆栈溢出,在Novell网站上提交错误或直接通过电子邮件发送MonoTouch的支持电子邮件.我们已将(托管和非托管)内存使用量减少到荒谬的低点,但由于此问题,应用程序仍然崩溃.
在短期内,我唯一想到的解决方法是在启动时分配一大块内存(2-5MB),将其设为PIN,以便垃圾收集器永远不会触及它,并编写我自己的分配器来分配部分内存.这个内存块根据需要阻止我的应用程序.但如果这是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) <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) <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. =================================================================