(СМОТРИТЕ ОБНОВЛЕНИЕ НА НОМЕРЕ)
Недавно я начал получать странный и редкий крах моего 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 и матовой для их помощи. Используя трассировку стека обратного вызова и ведения журнала уведомлений, я обнаружил, что этот точный стек возникает тогда и только тогда, когда уведомление UIApplicationResumedNotification
запускается как часть возврата из фона. И угадайте, что это - это некоторое уведомление "private", и у него нет общего идентификатора. Он не имеет 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 - это обратный вызов "observer", который я добавил для отладки только сейчас.
Чтобы доказать точку, я сознательно пропустил вызов removeObserver:
из одного из моих объектов, чтобы создать зомби/исключение, а трассировка стека по-прежнему включала _CFXNotificationPost + 1426
, а затем сбой с EXC_BAD_ACCESS
в objc_msgSend + 16
, как и в моем первоначальном крахе.
Таким образом, это означает, что кто-то зарегистрировал наблюдателя для UIApplicationResumedNotification
и не удалил его до того, как наблюдатель был освобожден. Исходя из того факта, что я никогда не регистрировался для такого уведомления, могу предположить, что этот крах не является моей ошибкой. Тем не менее остается вопрос - чей это тогда? Интересно, кто на самом деле регистрируется для этого уведомления в любом случае...
ОБНОВЛЕНИЕ 2
Пока я все еще жду, чтобы увидеть, есть ли какие-либо изменения с этой ошибкой в новой версии моего приложения, я получил еще один сбой в предыдущей версии, вызванной этим. Оказывается, что все регистры для UIApplicationResumedNotification
задает для него селектор _applicationResuming:
. Я сомневаюсь в том, что любой вариант использования.