SEGV_ACCERR在dealloc中调用 removeObserver:self]

我真的不知道这是怎么发生的。 我有一个使用ARC的应用程序。 我的视图控制器大多数注册NSNotifications。 所有注册都在主线程完成。

发生内存警告时,用于每个不可见选项卡的导航控制器都将被清空,并因此被释放。 在这种情况下,一个导航控制器及其视图控制器被释放,并且视图控制器在其dealloc方法中崩溃了应用程序。

具体来说,它是从所有NSNotificationCenter通知中删除自己。

dealloc方法也运行在主线程中,所以我不明白这可能是一个线程问题。

崩溃的行是-[SearchTabViewController dealloc] (SearchTabViewController.m:44)

该代码中的行是: [[NSNotificationCenter defaultCenter] removeObserver:self];

实际的崩溃原因似乎是objc_msgSend引用一个解除分配的对象。

问题在于只有2个消息在这里发送, NSNotificationCenter类的defaultCenter消息(它永远不会是一个无效的引用,因为它是一个类), removeObserver:消息到默认的中心对象(也永远不会是释放,因为它是一个单身人士)。

唯一被引用的另一个对象是self,它不能被释放,因为我们仍然在这个对象的“dealloc”方法中…基本上这个崩溃不应该发生。

有什么我在这里失踪? 下面的崩溃日志的相关部分:


 Exception Type: SIGSEGV Exception Codes: SEGV_ACCERR at 0xe0000008 Crashed Thread: 0 Thread 0 Crashed: 0 libobjc.A.dylib 0x000035b0 objc_msgSend + 16 1 Anghami Beta 0x000c7473 -[SearchTabViewController dealloc] (SearchTabViewController.m:44) 2 CoreFoundation 0x00003311 CFRelease + 101 3 CoreFoundation 0x0000d95d -[__NSArrayM dealloc] + 141 4 Anghami Beta 0x0033e73f -[EX2NavigationController .cxx_destruct] (EX2NavigationController.m:51) 5 libobjc.A.dylib 0x00007f3d object_cxxDestructFromClass(objc_object*, objc_class*) + 57 6 libobjc.A.dylib 0x000050d3 objc_destructInstance + 35 7 libobjc.A.dylib 0x000053a7 object_dispose + 15 8 UIKit 0x000cec89 -[UIViewController dealloc] + 1181 9 CoreFoundation 0x00003311 CFRelease + 101 10 CoreFoundation 0x0000da13 -[__NSArrayI dealloc] + 79 11 libobjc.A.dylib 0x00005489 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 169 12 CoreFoundation 0x00005441 _CFAutoreleasePoolPop + 17 13 CoreFoundation 0x00095f41 __CFRunLoopRun + 1297 14 CoreFoundation 0x00008ebd CFRunLoopRunSpecific + 357 15 CoreFoundation 0x00008d49 CFRunLoopRunInMode + 105 16 GraphicsServices 0x000052eb GSEventRunModal + 75 17 UIKit 0x00057301 UIApplicationMain + 1121 18 Anghami Beta 0x0000334d main (main.m:17) 

所以事实certificate,崩溃日志是误导性的。 我最终能够在启用僵尸对象的情况下连接到debugging器。 崩溃的实际来源是一个加载器对象,它拥有这个控制器,因为它是委托,试图在控制器被释放后调用其中一个委托方法。

现在,在dealloc中,我们不需要载入器的代理,如果激活,取消载入,不会再有崩溃。


另外,值得注意的是,这个崩溃在模拟器中拒绝发生,但几乎每次都在设备上发生。 所以当追踪奇怪的内存错误时,不幸的是僵尸工具并不总是一个可行的工具,因为它需要应用程序在模拟器中运行。

所以下一个最好的办法是去编辑计划,并启用僵尸对象,然后build立和运行在设备上,并等待它崩溃。 你没有这样完整的保留/发布历史,但是在这种情况下,它可以提供足够的信息来追踪一个难以解决的问题。