【发布时间】:2012-09-26 12:08:35
【问题描述】:
(见底部更新)
最近,当我的 iPhone 应用程序从后台返回时,我开始遇到奇怪且罕见的崩溃。崩溃日志仅包含系统调用:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000138
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x34c715b0 objc_msgSend + 16
1 CoreFoundation 0x368b7034 _CFXNotificationPost + 1424
2 Foundation 0x34379d8c -[NSNotificationCenter postNotificationName:object:userInfo:] + 68
3 UIKit 0x37ddfec2 -[UIApplication _handleApplicationResumeEvent:] + 1290
4 UIKit 0x37c37d5c -[UIApplication handleEvent:withNewEvent:] + 1288
5 UIKit 0x37c376d0 -[UIApplication sendEvent:] + 68
6 UIKit 0x37c3711e _UIApplicationHandleEvent + 6150
7 GraphicsServices 0x36dea5a0 _PurpleEventCallback + 588
8 CoreFoundation 0x3693b680 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
9 CoreFoundation 0x3693aee4 __CFRunLoopDoSources0 + 208
10 CoreFoundation 0x36939cb2 __CFRunLoopRun + 642
11 CoreFoundation 0x368aceb8 CFRunLoopRunSpecific + 352
12 CoreFoundation 0x368acd44 CFRunLoopRunInMode + 100
13 GraphicsServices 0x36de92e6 GSEventRunModal + 70
14 UIKit 0x37c8b2fc UIApplicationMain + 1116
15 [MyAppName] 0x00083d60 main (main.m:20)
16 [MyAppName] 0x00080304 start + 36
这可能看起来像在 UIApplicationWillEnterForegroundNotification 或 UIApplicationDidBecomeActiveNotification 上调用的僵尸对象(根据堆栈跟踪中的 _handleApplicationResumeEvent 和它崩溃的时间猜测),但是:
- 我的所有班级都没有注册
UIApplicationDidBecomeActiveNotification,只有几个单身人士(永远活着)注册UIApplicationWillEnterForegroundNotification; - 我做了一些实验,结果发现
UIApplicationWillEnterForegroundNotification的发帖来自[UIApplication _sendWillEnterForegroundCallbacks:],并且它不在崩溃日志中。
对我来说,这一切都意味着我正在使用的某个库中存在错误,或者系统错误,并且崩溃发生在 iOS 5.1.1(发布版本)、iOS 6.0(发布版本)和一次iOS 6.0(调试版本)。我扫描了我正在使用的每个库并可以访问其源代码,但它们既没有注册 UIApplicationWillEnterForegroundNotification 也没有注册 UIApplicationDidBecomeActiveNotification。我唯一无法访问的库是 TestFlight,但崩溃发生在 TestFlight 的 1.0 和 1.1 版本上,我已经使用前者很长一段时间了,没有出现此类问题。
所以,总而言之,我不知道为什么会出现这种崩溃以及它来自什么。有什么想法吗?
更新 1
感谢 DarthMike 和 matt 的帮助,我对这个问题进行了更深入的调查。通过使用通知中心回调和记录堆栈跟踪,我发现当且仅当UIApplicationResumedNotification 通知作为从后台返回的一部分被触发时,才会出现这个确切的堆栈。你猜怎么着——这是一些“私人”通知,它没有对应的公共标识符。它没有userInfo,它的对象是UIApplication(与之前发布的许多其他通知一样)。显然我不使用它,我也没有任何库我有源代码。我什至在互联网上找不到任何合理的提及!我也非常怀疑 TestFlight 是罪魁祸首,因为在调试期间也发生了崩溃,而且我不会在调试模式下“起飞”TestFlight。
这是接收UIApplicationResumedNotification 的堆栈跟踪。偏移量都是相同的,但具有恒定的字节偏移量(2 或 4,取决于库 - 可能是因为它是调试堆栈跟踪,而不是发布):
0 [MyAppName] 0x0016f509 NotificationsCallback + 72
1 CoreFoundation 0x3598ce25 __CFNotificationCenterAddObserver_block_invoke_0 + 124
2 CoreFoundation 0x35911037 _CFXNotificationPost + 1426
3 Foundation 0x333d3d91 -[NSNotificationCenter postNotificationName:object:userInfo:] + 72
4 UIKit 0x36e39ec7 -[UIApplication _handleApplicationResumeEvent:] + 1294
5 UIKit 0x36c91d61 -[UIApplication handleEvent:withNewEvent:] + 1292
6 UIKit 0x36c916d5 -[UIApplication sendEvent:] + 72
7 UIKit 0x36c91123 _UIApplicationHandleEvent + 6154
8 GraphicsServices 0x35e445a3 _PurpleEventCallback + 590
9 CoreFoundation 0x35995683 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
10 CoreFoundation 0x35994ee9 __CFRunLoopDoSources0 + 212
11 CoreFoundation 0x35993cb7 __CFRunLoopRun + 646
12 CoreFoundation 0x35906ebd CFRunLoopRunSpecific + 356
13 CoreFoundation 0x35906d49 CFRunLoopRunInMode + 104
14 GraphicsServices 0x35e432eb GSEventRunModal + 74
15 UIKit 0x36ce5301 UIApplicationMain + 1120
16 [MyAppName] 0x000aa603 main + 390
17 [MyAppName] 0x000a41b0 start + 40
NotificationsCallback 是我为调试添加的“观察者”回调。
为了证明一点,我故意从我的一个对象中省略了 removeObserver: 调用以生成僵尸/异常,并且堆栈跟踪仍然包含 _CFXNotificationPost + 1426,然后在 @987654339 中出现 EXC_BAD_ACCESS 崩溃@,就像我最初的崩溃一样。
所以这只是意味着有人已经为UIApplicationResumedNotification 注册了一个观察者,并且在观察者被解除分配之前没有删除它。基于我从未注册过此类通知的事实,我可以假设这次崩溃不是我的错。问题仍然存在——那是谁呢?我想知道到底是谁注册了这个通知......
更新 2
虽然我仍在等待查看我的应用程序的新版本是否对此错误有任何更改,但我在以前的版本中遇到了另一个由此导致的崩溃。事实证明,无论为UIApplicationResumedNotification 注册什么,都会为其指定选择器_applicationResuming:。不过我怀疑这有什么用。
【问题讨论】:
-
“对我来说,所有这些都意味着我正在使用的某个库中存在错误,或者是系统错误。”我将给你最好的 Cocoa touch 编程建议。假设是你。
-
如果您使用的是 Localytics,那么这是他们图书馆的一个已知问题,他们已经为他们的图书馆发送了紧急更新
-
谢谢,Leftertis,但我不使用 Localytics,我使用 TestFlight。
-
对于这种错误,我通常会这样处理:删除应用程序的部分直到不会发生崩溃。您是否可以/容易地删除 TestFlight 的使用,或删除您正在使用的其他库,甚至删除代码中的 addObserver 调用?一个一个地删除应该会发现问题。如果是框架问题,那么如果没有任何对象注册任何通知,就会发生崩溃。
-
达斯迈克,我认为这不可能。有大量代码和几个库,我通过 TestFlight 收到崩溃,所以我需要它。这种崩溃非常很少发生,所以——即使我再也看不到它,也不意味着它不存在……我想暂时,我会忽略它并等待如果它再次发生。
标签: objective-c ios crash