mj2*_*008 17 memory-management xamarin.ios ios
我们有一个简单的问题,但原因很复杂.我们是经验丰富的开发人员,并且已经对可能导致它的原因进行了大量研究.我们希望MonoTouch开发人员能够与我们合作,以确定人们所面临的常见问题,而且目前还没有解决方案.我们已经为此工作了两个多星期,但未能解决它.
问题是:为什么我们的MonoTouch应用程序在垃圾收集器中崩溃?它并没有内存不足.
情况是我们有一个应用程序定期检查Web服务(可能每5秒).经过一段时间后,内存管理中止失败.这通常在大约一个半小时后发生,但可以是十分钟到一夜之间的任何地方.这种情况发生在我们所有的测试设备上(我们总共有7个测试设备,包括iOS3和iOS4,iPod Touch,iPhone和iPad(1和2).在查看StackOverflow之后,我们在计时器中添加了一个System.Gc.Collect.这改善了一些事情(失败需要更长的时间),但它并没有消失.还有一点值得补充的是,来自iPad的内存日志显示有777个免费模块,我们的应用程序使用了2041个,共有26488个有线页面.由于我们收集了垃圾,并且没有做出与我们之前5秒做的不同的事情,因此内存耗尽似乎很奇怪.
我们升级到MonoTouch 4.0.1,但还没有修复它.
计算器上可能出现的同一个问题的问题,但没有回答它:五六六六九〇五 /四五四五三八三/五四九二四六九/5426733
iPad2上发生故障的堆栈如下.失败可能发生在主线程或http线程中,但始终在此GC_序列中.我已经在下面列出了内存管理器GC_remap的代码,并进行了讨论.
Thread 10 Crashed: 0 libsystem_kernel.dylib 0x34b4da1c __pthread_kill + 8 1 libsystem_c.dylib 0x3646a3b4 pthread_kill + 52 2 libsystem_c.dylib 0x36462bf8 abort + 72 3 MyApp 0x004ca92c mono_handle_native_sigsegv (mini-exceptions.c:2249) 4 MyApp 0x004f2208 sigabrt_signal_handler (mini-posix.c:195) 5 libsystem_c.dylib 0x36475728 _sigtramp + 36 6 libsystem_c.dylib 0x3646a3b4 pthread_kill + 52 7 libsystem_c.dylib 0x36462bf8 abort + 72 8 MyApp 0x0061dc94 GC_remap (os_dep.c:2092) 9 MyApp 0x00611678 GC_allochblk_nth (allchblk.c:730) 10 MyApp 0x00611028 GC_allochblk (allchblk.c:561) 11 MyApp 0x0061d0e0 GC_new_hblk (new_hblk.c:253) 12 MyApp 0x006133d0 GC_allocobj (alloc.c:1116) 13 MyApp 0x00617d30 GC_generic_malloc_inner (malloc.c:136) 14 MyApp 0x00617f40 GC_generic_malloc (malloc.c:192) 15 MyApp 0x00618264 GC_malloc_atomic (malloc.c:262) 16 MyApp 0x005a46d4 mono_object_allocate_ptrfree (object.c:4221) 17 MyApp 0x005a4aa0 mono_string_new_size (object.c:4848) 18 MyApp 0x005c1b14 ves_icall_System_String_InternalAllocateStr (string-icalls.c:213) 19 MyApp 0x002d34c4 wrapper_managed_to_native_string_InternalAllocateStr_int + 52 20 MyApp 0x002cff5c string_ToLower_System_Globalization_CultureInfo + 56 21 MyApp 0x003e6ac0 System_Net_WebRequest_GetCreator_string + 40 22 MyApp 0x003e694c System_Net_WebRequest_Create_System_Uri + 48 23 MyApp 0x003e68d8 System_Net_WebRequest_Create_string + 64 24 MyApp 0x004489c4 MyApp_Services_Client_GetResponseContent_string + 152 25 MyApp 0x00446288 MyApp_Services_Client_GetCurrentQuestion_long_long + 916 26 MyApp 0x00196fcc MyApp_Iphone_RootViewController_RetrieveCurrentQuestion + 868 27 MyApp 0x002e6368 System_Threading_Thread_StartUnsafe + 168 28 MyApp 0x00306890 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 192 29 MyApp 0x004b0274 mono_jit_runtime_invoke (mini.c:5746) 30 MyApp 0x0059f924 mono_runtime_invoke (object.c:2756) 31 MyApp 0x005a1350 mono_runtime_delegate_invoke (object.c:3421) 32 MyApp 0x005ca884 start_wrapper_internal (threads.c:788) 33 MyApp 0x005ca924 start_wrapper (threads.c:830) 34 MyApp 0x005ef4b8 thread_start_routine (wthreads.c:285) 35 MyApp 0x0061f1d0 GC_start_routine (pthread_support.c:1468) 36 libsystem_c.dylib 0x3646a30a _pthread_start + 242 37 libsystem_c.dylib 0x3646bbb4 thread_start + 0
这是一个似乎是故障点的GC_remap代码,从https://github.com/mono/mono/blob/master/libgc/os_dep.c
#ifdef NACL { /* NaCl doesn't expose mprotect, but mmap should work fine */ void * mmap_result; mmap_result = mmap(start_addr, len, PROT_READ | PROT_WRITE | OPT_PROT_EXEC, MAP_PRIVATE | MAP_FIXED | OPT_MAP_ANON, zero_fd, 0/* offset */); if (mmap_result != (void *)start_addr) ABORT("mmap as mprotect failed"); /* Fake the return value as if mprotect succeeded. */ result = 0; } #else /* NACL */ result = mprotect(start_addr, len, PROT_READ | PROT_WRITE | OPT_PROT_EXEC); #endif /* NACL */ if (result != 0) { GC_err_printf3( "Mprotect failed at 0x%lx (length %ld) with errno %ld\n", start_addr, len, errno); ABORT("Mprotect remapping failed"); } GC_unmapped_bytes -= len;
似乎ABORT是由mprotect功能失败引起的.我们无法获得失败代码,因为问题不会在模拟器上显现出来.mprotect函数似乎只是将内存标记为可读/写/执行.内存管理器如何传递导致其失败的参数?可能是传递了错误的指针,还是错误的长度?或者iOS上的某些区域或边界处理方式不同?
用于GC_allochblk_nth的https://github.com/mono/mono/blob/master/libgc/allchblk.c中的代码表示仅在找到的内存块有效时才调用GC_remap函数.(此文件与堆栈跟踪的行号不完全匹配,因此可能不是完全相同的文件.)
http://developer.apple.com/library/ios/#documentation/System/Conceptual/ManPages_iPhoneOS/man2/mprotect.2.html表示它可能会失败,EACCES,EINVAL,ENOTSUP分别为13,22和45 .其中一篇关于SO的报告称他们得到错误12(ENOMEM).我不确定这意味着什么,因为mprotect不应该分配内存,文档并没有说这是有效的.
http://linux.die.net/man/2/mprotect中更通用的文档表明ENOMEM可能由"无法分配内部内核结构"引起.或者:[addr,addr + len]范围内的地址是对进程的地址空间无效,或指定一个或多个未映射的页面." 怎么会这样?
我们非常感谢有关如何推动这一进展的任何建议.我们没有做除C#代码以外的任何事情,除了定期的https读取之外没有做任何其他事情.我们可以做些什么来改进调试(我们无法追踪任何因为iOS被杀死的应用程序).我们已经尝试创建一个更简单的演示,但它不会快速失败,值得使用.如果Novell MonoTouch开发人员需要我们的源代码,我们可以提供明显的机密性.
归档时间: |
|
查看次数: |
1708 次 |
最近记录: |