iOS程序異常crash捕獲與攔截
對于iOS應用try-catch并不能捕獲所有異常,也就是說有時候我們加上了try-catch可是程序還是會Crash,目前我所總結有兩種:一種是由EXC_BAD_ACCESS引起的,原因是訪問了不屬于本進程的內存地址,有可能是訪問已被釋放的內存;另一種是未被捕獲的Objective-C異常(NSException),導致程序向自身發送了SIGABRT信號而崩潰。其實對于未捕獲的Objective-C異常,我們是有辦法將它記錄下來的,如果日志記錄得當,能夠解決絕大部分崩潰的問題。下面對于UI線程與后臺線程分別說明。
傳統的捕獲異常的方式中所熟知try-catch-finally,但有些時候一些iOS系統的api是原生的C語法格式例如:sqlite3.c,UnGzip.c這些是不支持OC或者C++的try-catch機制即使有異常也是捕獲不到,或者是一些內存的問題等在try里面還是會無情的Crash。
iOSSDK中提供了一個現成的函數NSSetUncaughtExceptionHandler用來做異常處理,但功能非常有限,而引起崩潰的大多數原因如:內存訪問錯誤,重復釋放等錯誤就無能為力了,因為這種錯誤它拋出的是Signal,所以必須要專門做Signal處理。代碼如下
通過上圖的操作我們就完成了iOS SDK給我們提供的捕捉異常處理,我們只需要在HandleException方法中紀錄我們的異常信息即可。但這僅僅是捕獲一般的OC異常信息,對于Signal異常信號我們仍然無法捕獲到,此時我們就需要去注冊一些Signal信號來幫助我們捕獲Signal異常。首先介紹一下Signal信號:
signal。既信號量,ios是Linux內核,在程序發生未捕獲異常時,程序會向自身發送信號(SIGABRT、SIGBUS、SIGHUP等。。。),然后程序直接閃退。。。有時候這是無可避免的。作為一款優秀的軟件,必須要有異常報告模塊,讓用戶給你發送異常報告信息。這樣才能根據異常信息來做相應地Debug工作。在iOS SDK
signal.h里面有31種信號方式這里不做一一解釋。
下面說一下怎么注冊這些信號量來幫助我們記錄到異常信息。代碼如下:
上圖中的signal(SIGHUP, void(*)(int));方法為iOS signal.h中的注冊信號量的方法其中第二個參數為收到信號的回調函數,我們通過這個回調函數可以根據我們的需求做一些處理。
小結:try-Catch只能幫助我們攔截一些bug或者幫助我們提供一些錯誤信息,要從根本上解決程序的問題還需要不斷的調試,優化。
作者:Olivia_Zqy