崩溃NSManagedObject版本:“objc_msgSend()select器名称:_queueForDealloc”

我有很多用户通过HockeyApp得到了一个奇怪的崩溃,下面的堆栈跟踪。 这似乎与NSManagedObject被释放在不同的调度队列中有关…但我没有得到任何象征性的问题可能。 这似乎是一个内存pipe理问题,但我使用ARC,所以不知道如何过度释放一个NSManagedObject。

这是我得到的崩溃报告(主线程在不同时间显示不同的痕迹):

Code Type: ARM-64 Parent Process: launchd [1] Date/Time: 2014-05-12T05:43:54Z OS Version: iPhone OS 7.0.6 (11B651) Report Version: 104 Exception Type: SIGSEGV Exception Codes: SEGV_ACCERR at 0x1c3dbeb8 Crashed Thread: 2 Application Specific Information: objc_msgSend() selector name: _queueForDealloc: Thread 0: 0 CoreFoundation 0x000000018e384618 CFNumberGetType + 0 1 CoreFoundation 0x000000018e3333b8 _CFAppendXML0 + 2768 2 CoreFoundation 0x000000018e333304 _CFAppendXML0 + 2588 3 CoreFoundation 0x000000018e332268 _CFPropertyListCreateXMLData + 196 4 Foundation 0x000000018ef152f4 -[NSDictionary(NSDictionary) writeToFile:atomically:] + 232 5 SimpleList 0x00000001001ae48c __55-[SharedSettingController writeToContactsReferenceFile]_block_invoke (SharedSettingController.m:620) 6 libdispatch.dylib 0x000000019a974420 _dispatch_call_block_and_release + 20 7 libdispatch.dylib 0x000000019a9743e0 _dispatch_client_callout + 12 8 libdispatch.dylib 0x000000019a97756c _dispatch_main_queue_callback_4CF + 340 9 CoreFoundation 0x000000018e3e6d64 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8 10 CoreFoundation 0x000000018e3e50a4 __CFRunLoopRun + 1448 11 CoreFoundation 0x000000018e325b38 CFRunLoopRunSpecific + 448 12 GraphicsServices 0x0000000193d4b830 GSEventRunModal + 164 13 UIKit 0x00000001913640e8 UIApplicationMain + 1152 14 SimpleList 0x000000010006347c _mh_execute_header (main.m:18) 15 libdyld.dylib 0x000000019a98faa0 start + 0 Thread 1: 0 libsystem_kernel.dylib 0x000000019aa71ac8 kevent64 + 8 1 libdispatch.dylib 0x000000019a975d78 _dispatch_mgr_thread + 48 Thread 2 Crashed: 0 libobjc.A.dylib 0x000000019a39f9d0 objc_msgSend + 16 1 CoreData 0x000000018e13b284 -[NSManagedObject release] + 168 2 CoreData 0x000000018e131154 -[_PFArray dealloc] + 96 3 libobjc.A.dylib 0x000000019a3a13d4 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 520 4 libdispatch.dylib 0x000000019a97b428 _dispatch_root_queue_drain + 440 5 libdispatch.dylib 0x000000019a97b638 _dispatch_worker_thread2 + 72 6 libsystem_pthread.dylib 0x000000019ab09918 _pthread_wqthread + 352 7 libsystem_pthread.dylib 0x000000019ab097a8 start_wqthread + 0 Thread 3: 0 libsystem_kernel.dylib 0x000000019aa71cc0 mach_msg_trap + 8 1 CoreFoundation 0x000000018e3e6cac __CFRunLoopServiceMachPort + 180 2 CoreFoundation 0x000000018e3e4e3c __CFRunLoopRun + 832 3 CoreFoundation 0x000000018e325b38 CFRunLoopRunSpecific + 448 4 Foundation 0x000000018ef127fc +[NSURLConnection(Loader) _resourceLoadLoop:] + 344 5 Foundation 0x000000018efa0770 __NSThread__main__ + 996 6 libsystem_pthread.dylib 0x000000019ab0c1b0 _pthread_body + 164 7 libsystem_pthread.dylib 0x000000019ab0c108 _pthread_start + 136 8 libsystem_pthread.dylib 0x000000019ab097b0 thread_start + 0 Thread 4: 0 libsystem_kernel.dylib 0x000000019aa8a76c __select + 8 1 libsystem_pthread.dylib 0x000000019ab0c1b0 _pthread_body + 164 2 libsystem_pthread.dylib 0x000000019ab0c108 _pthread_start + 136 3 libsystem_pthread.dylib 0x000000019ab097b0 thread_start + 0 Thread 5: 0 libsystem_kernel.dylib 0x000000019aa8ae74 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0x000000019ab097a8 start_wqthread + 0 Thread 6: 0 libsystem_kernel.dylib 0x000000019aa8ae74 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0x000000019ab097a8 start_wqthread + 0 Thread 7: 0 libsystem_kernel.dylib 0x000000019aa8ae74 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0x000000019ab097a8 start_wqthread + 0 Thread 2 crashed with ARM-64 Thread State: pc: 0x000000019a39f9d0 fp: 0x0000000102b479c0 sp: 0x0000000102b479a0 x0: 0x00000001782451f0 x1: 0x000000018e2eeb56 x2: 0x00000001705336a0 x3: 0x000000019aac3d18 x4: 0x0000000000000001 x5: 0x0000000000000010 x6: 0x000000017013f900 x7: 0x0000000000000000 x8: 0x000000019ad5bdb8 x9: 0x000000001c3dbea8 x10: 0x0000000000000000 x11: 0x000000230000003f x12: 0x000000014f073410 x13: 0xbadd5bcc1c3dbead x14: 0xffffffffffffffff x15: 0x0000000000000001 x16: 0x000000019a39f9c0 x17: 0x000000018e13b1d8 x18: 0x0000000000000000 x19: 0x00000001705336a0 x20: 0x000000019ad7b000 x21: 0x000000019adc9200 x22: 0x000000019ad7b000 x23: 0x0000000000000715 x24: 0x0000000000000010 x25: 0x0000000102a64038 x26: 0xa3a3a3a3a3a3a3a3 x27: 0x0000000000000001 x28: 0x0000000000000000 lr: 0x000000018e13b284 cpsr: 0x0000000020000000 

在启动时,我启动了一些调度队列来做一些后台工作(他们使用一个单独的MOC来加载pipe理对象并处理它们),所以这些可能是负责任的,但队列被标记在我的应用程序中,堆栈跟踪似乎没有显示哪个队列负责(如果是我自己的队列)。 我已经运行与NSZombies启用应用程序,但没有帮助。 我也运行了静态分析工具,这不会产生任何东西。

任何想法可能会导致这个问题,我能做些什么来debugging呢?

编辑:

我敢肯定,我可以将问题区域隔离为启动应用程序后调用的一段代码:

 SLAppDelegate *delegate = (SLAppDelegate *) [[UIApplication sharedApplication] delegate]; dispatch_async(delegate.coreDataController.filterMainQueue, ^{ NSManagedObjectContext *backgroundContextImage = [[NSManagedObjectContext alloc] init]; [backgroundContextImage setPersistentStoreCoordinator: delegate.coreDataController.persistentStoreCoordinator]; NSArray *items = [Person getAllPersonsWithContext: backgroundContextImage]; // possibly update some of the items dispatch_async(dispatch_get_main_queue(), ^{ // writes the file inside another dispatch_asyn(dispatch_get_main_queue) [[SharedSettingController sharedSettings] writeToContactsReferenceFile]; }; }); 

我只是不确定这有什么问题。 它工作正常99%的时间。 但是,这1%是导致一些崩溃,我很想得到解决。

NSOperation使用私有托pipe对象上下文时,我们遇到了类似的问题,我们通过削弱任何参数并使用私有的@autoreleasepool来解决这个@autoreleasepool 。 我将在下面进一步阐述。

我们目前的设置有一个NSOperationQueue ,它有一个长期运行的计算,我们在后台做。 该操作首先创build一个私有托pipe对象上下文,其中父对象作为主对象上下文并访问其对象。

与此同时,我们在其他地方有一个单独的NSOperationQueue ,用于同步服务器中的新数据,可能会添加,更新或删除计算操作使用的对象。

我们首先看到了一大堆这样的崩溃,唯一的办法就是让计算和同步操作不断运行,5-10分钟之后,我们会看到类似下面的崩溃:

 Thread : Crashed: background queue :: NSOperation 0x18f43c90 0 libobjc.A.dylib 0x36f11f46 objc_msgSend + 5 1 CoreData 0x2928408f -[NSManagedObject release] + 166 2 CoreData 0x2927b4d7 -[_PFArray dealloc] + 94 3 libobjc.A.dylib 0x36f201a9 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 404 4 CoreFoundation 0x294713a9 _CFAutoreleasePoolPop + 16 5 Foundation 0x2a1b6453 -[__NSOperationInternal _start:] + 1058 6 Foundation 0x2a25b44b __NSOQSchedule_f + 186 7 libdispatch.dylib 0x3746d651 _dispatch_queue_drain + 952 8 libdispatch.dylib 0x3746809d _dispatch_queue_invoke + 84 9 libdispatch.dylib 0x3746eba1 _dispatch_root_queue_drain + 320 10 libdispatch.dylib 0x3746fcd7 _dispatch_worker_thread3 + 94 11 libsystem_pthread.dylib 0x375c6e31 _pthread_wqthread + 668 Thread : Crashed: background queue :: NSOperation 0x1db59e80 0 libsystem_kernel.dylib 0x3722edfc __pthread_kill + 8 1 libsystem_pthread.dylib 0x372acd37 pthread_kill + 62 2 libsystem_c.dylib 0x371ce909 abort + 76 3 libsystem_malloc.dylib 0x37258331 szone_size 4 libobjc.A.dylib 0x36bf1621 object_dispose + 20 5 CoreData 0x28ec571d -[_PFManagedObjectReferenceQueue dealloc] + 80 6 CoreData 0x28e5630f -[NSManagedObject dealloc] + 166 7 CoreData 0x28e55217 -[_PFManagedObjectReferenceQueue _queueForDealloc:] + 246 8 CoreData 0x28e5508f -[NSManagedObject release] + 166 9 CoreData 0x28e4c4d7 -[_PFArray dealloc] + 94 10 libobjc.A.dylib 0x36c031a9 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 404 11 CoreFoundation 0x29042149 _CFAutoreleasePoolPop + 16 12 Foundation 0x29d88c23 -[__NSOperationInternal _start:] + 1058 13 Foundation 0x29e2dc1b __NSOQSchedule_f + 186 14 libdispatch.dylib 0x371505b1 _dispatch_queue_drain + 952 15 libdispatch.dylib 0x3714af85 _dispatch_queue_invoke + 84 16 libdispatch.dylib 0x37151b9b _dispatch_root_queue_drain + 338 17 libdispatch.dylib 0x37152cd7 _dispatch_worker_thread3 + 94 18 libsystem_pthread.dylib 0x372a9e31 _pthread_wqthread + 668 Thread : Crashed: NSOperationQueue Serial Queue 0 libsystem_kernel.dylib 0x396871f0 __pthread_kill + 8 1 libsystem_pthread.dylib 0x396ef7b7 pthread_kill + 58 2 libsystem_c.dylib 0x39637ff9 abort + 76 3 libsystem_malloc.dylib 0x396aed25 szone_size 4 libobjc.A.dylib 0x390d93a9 object_dispose + 20 5 CoreData 0x2e3d4081 -[_PFManagedObjectReferenceQueue dealloc] + 80 6 CoreData 0x2e3655b7 -[NSManagedObject dealloc] + 166 7 CoreData 0x2e364501 -[_PFManagedObjectReferenceQueue _queueForDealloc:] + 244 8 CoreData 0x2e36437d -[NSManagedObject release] + 164 9 CoreData 0x2e35b867 -[_PFArray dealloc] + 94 10 libobjc.A.dylib 0x390e20d3 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 358 11 CoreFoundation 0x2e5294c1 _CFAutoreleasePoolPop + 16 12 Foundation 0x2ef29999 -[__NSOperationInternal _start:] + 1064 13 Foundation 0x2efcd745 __NSOQSchedule_f + 60 14 libdispatch.dylib 0x395c0cbd _dispatch_queue_drain + 488 15 libdispatch.dylib 0x395bdc6f _dispatch_queue_invoke + 42 16 libdispatch.dylib 0x395c15f1 _dispatch_root_queue_drain + 76 17 libdispatch.dylib 0x395c18dd _dispatch_worker_thread2 + 56 18 libsystem_pthread.dylib 0x396ecc17 _pthread_wqthread + 298 

我们多次查看代码,无法确定它为什么崩溃。 我们尝试了启用NSZombies,但是在我们能够得到一个repro之前就会耗尽内存。

我们最终做的是以下两件事:

@autoreleasepool

在我们的[privateObjectContext performBlockAndWait:^{…}]内的[privateObjectContext performBlockAndWait:^{…}]中,我们将所有的代码包装在@autoreleasepool{…} 。 这样,在该代码块中检索的所有NSManagedObjects将在离开performBlockAndWait之前标记为释放。

weakify / strongify

任何包含NSManagedObjects的参数在传递到块之前都是弱化的,并且在块中强化一次。 因为我们不再强烈地提到它们,所以如果它们在我们等待NSOperation启动时变得过时,它们就可以被释放。 这里有一篇关于如何弱化/强化作品的好文章: http ://blog.aceontech.com/post/111694918560/weakifyself-a-more-elegant-solution-to