【问题标题】:SEGV_ACCERR calling [[NSNotificationCenter defaultCenter] removeObserver:self] in deallocSEGV_ACCERR 在 dealloc 中调用 [[NSNotificationCenter defaultCenter] removeObserver:self]
【发布时间】:2012-10-05 17:54:26
【问题描述】:

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

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

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

dealloc 方法也在主线程中运行,所以我看不出这怎么可能是线程问题。

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

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

实际的崩溃原因似乎是objc_msgSend 引用了一个已释放的对象。

问题在于这里只发送了 2 条消息,defaultCenter 消息发送到 NSNotificationCenter 类(它永远不会是无效引用,因为它是一个类)和 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)

【问题讨论】:

    标签: iphone objective-c ios foundation


    【解决方案1】:

    结果证明崩溃日志具有误导性。当连接到启用了僵尸对象的调试器时,我最终能够实现它。崩溃的实际来源是一个加载器对象,该对象将此控制器作为它的委托,试图在控制器被释放后调用其中一个委托方法。

    现在在 dealloc 中,我将加载器的委托归零并取消加载(如果处于活动状态),然后就不会再崩溃了。


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

    所以下一个最好的办法是去编辑方案并在那里启用僵尸对象,然后在设备上构建和运行并等待它崩溃。您无法通过这种方式获得完整的保留/发布历史记录,但在本例中,它可以提供足够的信息来追踪原本难以捉摸的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-04
      • 2016-02-11
      • 1970-01-01
      • 2017-06-09
      • 1970-01-01
      • 2012-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多