[英]iOS app crashes on resuming
(見底部更新)
最近,當我的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上( debug build)。 我掃描了我正在使用的每個庫並且可以訪問源代碼,並且它們既不注冊UIApplicationWillEnterForegroundNotification
也不注冊UIApplicationDidBecomeActiveNotification
。 我無法訪問的唯一庫是TestFlight,但崩潰發生在1.0和1.1版本的TestFlight上,而且我已經使用前者已經有一段時間了,沒有這樣的問題。 所以,總結一下,我不知道為什么會出現這種崩潰,它是什么來的。 有任何想法嗎?
更新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
然后在objc_msgSend + 16
與EXC_BAD_ACCESS
崩潰,就像在我的原來的崩潰。 所以這只是意味着有人已經注冊了UIApplicationResumedNotification
的觀察者,並且在觀察者被釋放之前沒有刪除它。 基於我從未注冊過此類通知的事實,我可以認為這次崩潰不是我的錯。 問題仍然存在 - 那是誰呢? 我想知道究竟誰注冊了這個通知......
更新2
雖然我還在等待我的應用程序的新版本上的這個錯誤是否有任何變化,但是由於此原因導致我的先前版本出現了另一次崩潰。 事實證明, UIApplicationResumedNotification
任何寄存器都指定了selector _applicationResuming:
for it。 我懷疑這有什么用處。
我在運行IOS 6.0.1的設備的崩潰報告中有完全相同的堆棧跟蹤。 我設法通過以下模式在Simulator上重現問題:
message is sent to a which I am releasing as a reaction to Memory Warning. 經過大量的調試后,我發現消息被發送到 ,我將其作為對Memory Warning的反應而發布。 我在IOS 5.1下測試了相同的模式,但它沒有導致崩潰。 由於某些原因,IOS 6 UITextField注冊了ApplicationResumeEvent(可能並不總是在鍵盤出現之后)。
我的解決方法是在釋放它之前從NSNotificationCenter中刪除此對象:
[[NSNotificationCenter defaultCenter] removeObserver:self.placeFld];
self.placeFld = nil;
我剛遇到這個問題並找到了一個不涉及刪除通知的解決方案。 在我們的例子中,有一些舊代碼正在執行此操作:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
// other stuff
}
我不知道為什么我們有這個,但它現在已經消失了,崩潰消失了。 看來,在這種情況下,當searchBarTextDidBeginEditing被調用時,在搜索欄的文本編輯字段上調用孤立的第一響應者,然后一旦擁有此UISearchBar的視圖控制器被解除分配,我們就會崩潰,並且我們執行了后台/前台操作舞蹈。
因人而異
斷點-[NSNotificationCenter postNotificationName:object:userInfo:]
。 它試圖向一個不再存在的對象發送通知,或類似的東西。 您可能會錯誤管理自己的通知或自己的對象。
如果您尚未使用它,請考慮切換到ARC。
使用靜態分析儀。 它可以找到潛在的內存問題。
可能是很多東西,但我認為檢查注冊任何UIApplication通知的代碼會更好。 您實際上並不知道哪個通知會觸發錯誤。
此外,是否有任何對象在AppDelegate上保留/持有強大的參考? 它可能會導致一些奇怪的保留周期,從而導致崩潰。
我從未見過XCode不當行為造成的這種崩潰。
編輯:粘貼頭文件中的所有通知。 可能有點矯枉過正,但有些可以通過app resume / from background發送
UIKIT_EXTERN NSString *const UIApplicationDidEnterBackgroundNotification NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSString *const UIApplicationWillEnterForegroundNotification NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSString *const UIApplicationDidFinishLaunchingNotification;
UIKIT_EXTERN NSString *const UIApplicationDidBecomeActiveNotification;
UIKIT_EXTERN NSString *const UIApplicationWillResignActiveNotification;
UIKIT_EXTERN NSString *const UIApplicationDidReceiveMemoryWarningNotification;
UIKIT_EXTERN NSString *const UIApplicationWillTerminateNotification;
UIKIT_EXTERN NSString *const UIApplicationSignificantTimeChangeNotification;
UIKIT_EXTERN NSString *const UIApplicationWillChangeStatusBarOrientationNotification; // userInfo contains NSNumber with new orientation
UIKIT_EXTERN NSString *const UIApplicationDidChangeStatusBarOrientationNotification; // userInfo contains NSNumber with old orientation
UIKIT_EXTERN NSString *const UIApplicationStatusBarOrientationUserInfoKey; // userInfo dictionary key for status bar orientation
UIKIT_EXTERN NSString *const UIApplicationWillChangeStatusBarFrameNotification; // userInfo contains NSValue with new frame
UIKIT_EXTERN NSString *const UIApplicationDidChangeStatusBarFrameNotification; // userInfo contains NSValue with old frame
UIKIT_EXTERN NSString *const UIApplicationStatusBarFrameUserInfoKey; // userInfo dictionary key for status bar frame
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsURLKey NS_AVAILABLE_IOS(3_0); // userInfo contains NSURL with launch URL
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsSourceApplicationKey NS_AVAILABLE_IOS(3_0); // userInfo contains NSString with launch app bundle ID
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsRemoteNotificationKey NS_AVAILABLE_IOS(3_0); // userInfo contains NSDictionary with payload
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsLocalNotificationKey NS_AVAILABLE_IOS(4_0); // userInfo contains a UILocalNotification
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsAnnotationKey NS_AVAILABLE_IOS(3_2); // userInfo contains object with annotation property list
UIKIT_EXTERN NSString *const UIApplicationProtectedDataWillBecomeUnavailable NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSString *const UIApplicationProtectedDataDidBecomeAvailable NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsLocationKey NS_AVAILABLE_IOS(4_0); // app was launched in response to a CoreLocation event.
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsNewsstandDownloadsKey NS_AVAILABLE_IOS(5_0); // userInfo contains an NSArray of NKAssetDownlo
我做了一些事情來清理甲板,然后再調試一些奇怪的崩潰。
Build Clean(刪除本地緩存的文件)。
從模擬器/設備中刪除應用程序(有時會緩存XIB)。
重新啟動Xcode(當Xcode與當前設置不同步時,有一些奇怪的錯誤)。
然后,再試一次。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.