iOS 应用程序在恢复时崩溃 [英] iOS app crashes on resuming
问题描述
(见底部更新)
最近,当我的 iPhone 应用程序从后台返回时,我开始遇到奇怪且罕见的崩溃.崩溃日志仅包含系统调用:
Recently I've started getting a weird and rare crash of my iPhone app when it returns from background. The crash log consists of system calls only:
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
猜测以及它崩溃的时间),但是:
This might look like a zombie object being called on UIApplicationWillEnterForegroundNotification
or UIApplicationDidBecomeActiveNotification
(guessing by _handleApplicationResumeEvent
in stack trace and the time when it crashes), but:
- 我的所有类都没有注册
UIApplicationDidBecomeActiveNotification
,只有几个单身人士(永远活着)注册了UIApplicationWillEnterForegroundNotification
; - 我做了一些实验,结果发现发布
UIApplicationWillEnterForegroundNotification
来自[UIApplication _sendWillEnterForegroundCallbacks:]
,并且它不在崩溃日志中.
- None of my classes register for
UIApplicationDidBecomeActiveNotification
, and only a couple of singletons (that stay alive forever) register forUIApplicationWillEnterForegroundNotification
; - I've done some experimenting, and it turns out that posting
UIApplicationWillEnterForegroundNotification
goes from[UIApplication _sendWillEnterForegroundCallbacks:]
, and it isn't in the crash log.
对我来说,这一切都意味着我正在使用的某个库中存在错误,或者系统错误,并且崩溃发生在 iOS 5.1.1(发布版本)、iOS 6.0(发布版本)和一次iOS 6.0(调试版本).我扫描了我正在使用的每个库并可以访问其源代码,但它们既没有注册 UIApplicationWillEnterForegroundNotification
也没有注册 UIApplicationDidBecomeActiveNotification
.我唯一无法访问的库是 TestFlight,但崩溃发生在 TestFlight 的 1.0 和 1.1 版本上,我已经使用前者很长一段时间了,没有出现此类问题.所以,总而言之,我不知道为什么会出现这种崩溃以及它来自什么.有什么想法吗?
For me, all this implies a bug in some library I'm using, or a system bug, and the crash occurred once on iOS 5.1.1 (release build), once on iOS 6.0 (release build) and once on iOS 6.0 (debug build). I scanned every library I'm using and have access to the source code for, and they aren't registering for neither UIApplicationWillEnterForegroundNotification
nor UIApplicationDidBecomeActiveNotification
. The only library I don't have access to is TestFlight, but the crash occurred on both 1.0 and 1.1 versions of TestFlight, and I've been using the former for quite a while now, without such problems.
So, summing up, I have no idea why has this crash come up and what's it coming from. Any ideas?
更新 1
感谢 DarthMike 和 matt 的帮助,我对这个问题进行了更深入的调查.通过使用通知中心回调和记录堆栈跟踪,我发现当且仅当 UIApplicationResumedNotification
通知作为从后台返回的一部分被触发时,才会出现这个确切的堆栈.你猜怎么着——这是一些私人"通知,它没有对应的公共标识符.它没有 userInfo
并且它的对象是 UIApplication
(与之前发布的许多其他通知一样).显然我不使用它,我也没有任何库我有源代码.我什至在互联网上找不到任何合理的提及!我也非常怀疑TestFlight是罪魁祸首,因为在调试过程中也发生了崩溃,而且我不会在调试模式下起飞"TestFlight.
I've investigated the issue a bit deeper, thanks to DarthMike and matt for their help. By using notification center callback and logging stack trace, I've discovered that this exact stack comes up when and only when UIApplicationResumedNotification
notification is fired as a part of returning from background. And guess what - it's some "private" notification and it doesn't have a public identifier counterpart. It doesn't have userInfo
and its object is UIApplication
(as many other notifications that are posted before this). Obviously I don't use it, neither does any library I have source code for. I can't even find any reasonable mentioning of it in the Internet! I also highly doubt that TestFlight is the culprit, because crash happened during debug too, and I don't "take off" TestFlight in debug mode.
这是接收 UIApplicationResumedNotification
的堆栈跟踪.偏移量都是相同的,但具有恒定的字节偏移量(2 或 4,取决于库 - 可能是因为它是调试堆栈跟踪,而不是发布):
Here's the stack trace for receiving UIApplicationResumedNotification
. The offsets are all the same but with a constant byte offset (2 or 4, depending on the library - probably because it's a debug stack tracing, not release):
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 是我为调试添加的观察者"回调.
NotificationsCallback is an "observer" callback I've added for debug just for now.
为了证明一点,我故意从我的一个对象中省略了 removeObserver:
调用以生成僵尸/异常,并且堆栈跟踪仍然包含 _CFXNotificationPost + 1426
然后在 objc_msgSend + 16
中出现 EXC_BAD_ACCESS
崩溃,就像我最初的崩溃一样.所以这只是意味着有人已经为 UIApplicationResumedNotification
注册了一个观察者,并且在观察者被释放之前没有删除它.基于我从未注册过此类通知的事实,我可以假设这次崩溃不是我的错.问题仍然存在——那是谁呢?我想知道到底是谁注册了这个通知......
Just to prove a point, I've deliberately omitted a removeObserver:
call from one of my objects to generate a zombie/exception, and stack trace still included _CFXNotificationPost + 1426
followed by a crash with EXC_BAD_ACCESS
in objc_msgSend + 16
, just as in my original crash.
So this just means that someone has registered an observer for UIApplicationResumedNotification
and haven't removed it before the observer was deallocated. Based on the fact that I never registered for such a notification, I can assume that this crash is not my fault. Still the question remains - whose it is then? I wonder who actually registers for this notification anyway...
更新 2
虽然我仍在等待查看我的应用程序的新版本中的此错误是否有任何更改,但我在之前的版本中遇到了另一个由此导致的崩溃.事实证明,对于 UIApplicationResumedNotification
的任何寄存器,都会为其指定选择器 _applicationResuming:
.不过我怀疑这有什么用.
While I'm still waiting to see if there are any changes with this bug on the new version of my app, I've got another crash on the previous version caused by this. Turns out that whatever registers for UIApplicationResumedNotification
, specifies selector _applicationResuming:
for it. I doubt that's of any use though.
推荐答案
我刚遇到这个问题,找到了一个不涉及删除通知的解决方案.在我们的例子中,有一个旧代码正在这样做:
I just ran into this issue and found a solution that did not involve removing notifications. In our case, there was old code that was doing this:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
// other stuff
}
我不知道我们为什么会有这个,但现在它已经消失了,崩溃也消失了.似乎在这种情况下,在调用 searchBarTextDidBeginEditing 时辞职第一响应者会孤立搜索栏的文本编辑字段上的通知,然后一旦拥有此 UISearchBar 的视图控制器被释放并且我们执行了背景/前景,我们就会崩溃跳舞.
I do not know why we had this, but it is gone now and the crash is gone. It appears that in this case, resigning first responder while searchBarTextDidBeginEditing is being called orphans a notification on the search bar's text edit field, and then we'd crash as soon as the view controller owning this UISearchBar was deallocated and we did the background / foreground dance.
YMMV
这篇关于iOS 应用程序在恢复时崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!