iOS Crash異常捕獲及快速分析

1.前言

  • crash認識
  • 一套系統(tǒng)鲁沥、一款app经窖、一個功能、甚至一行代碼都可能會出現(xiàn)crash,crash伴隨著我們的日常生活狭园,如果我們正在玩游戲,LOL打團時,游戲閃退、電腦死機专控,那就想要跳起來砸鍵盤了。質量太差的產(chǎn)品遏餐,會導致產(chǎn)品負面評價越來越多伦腐,用戶流失越來越嚴重,如果在關鍵環(huán)節(jié)出現(xiàn)了crash失都,比如下單蔗牡、支付等,那就會造成直接損失嗅剖。作為技術開發(fā),我們對于這種問題要抱有零容忍的態(tài)度嘁扼,雖然我們不可能做到 0 crash,但是我們要盡量避免項目中存在的crash
  • 為什么沒有0 crash
  • crash的原因有很多信粮,在工作中我們也有很多方法去避免造成crash,比如自定義一個安全處理方法趁啸,做好異常crash因素判斷强缘。但是為什么沒有一個0crash的系統(tǒng)呢,就不能提供給我們絕對穩(wěn)定可靠的API嗎不傅?
  • 個人認為旅掂,每個API的設計都有其作用價值。比如iOS系統(tǒng)提供的[NSAarray objectAtIndex:]方法访娶,如果出現(xiàn)越界就會crash商虐,在項目中也有[NSArray safetyObjctAtIndex:]這樣的自定義安全處理方法,越界時返回nil崖疤,但是返回nil秘车,就一定是安全的嗎?一定是符合所有場景需求的嗎劫哼?比如某一個代碼異常時叮趴,后面的代碼是否應該執(zhí)行,執(zhí)行是否會帶來其他的負面影響

2.異常指標

當開發(fā)階段出現(xiàn)crash時权烧,我們可以直接通過xcode定位crash堆棧眯亦,在測試階段crash時,我們勉強還可以直接拿到測試機連接xcode查看日志般码,但是線上用戶或者拿不到crash測試機的情況下妻率,我們需要自己收集crash日志

造成crash的異常主要類型

  • Objective-C uncaughtException異常
    • 這類異常通常可以手動捕獲侈询,處理@try...@catch...@finallly舌涨,在項目中有很多地方使用
NSArray *arr = @[@1,@2];
@try {
  [arr objectAtIndex:3];
} @catch (NSException *exp){

} @finally {

}
  • NSInvalidArgumentException,非法參數(shù)
    • nil參數(shù)
      • unrecognized selector sendt to instance
      • ...
    • NSRangeException,越界異常
  • 數(shù)組囊嘉,字符串獲取下標
  • NSGenericException温技,通用異常
  • for ...in 循環(huán)中對可遍數(shù)組進行增加或者刪除,在for( ; ; )中不會造成crash扭粱,但是容易造成邏輯上的錯誤舵鳞,需要注意
  • NSMallocException,內存分配異常
NSMutableData *mData = [[NSMutableData alloc] initWithCapacity:1];
NSUInteger len = 1844674407370955161;
[mData increaseLengthBy:len];


*** Terminating app due to uncaught exception 'NSMallocException', 
reason: 'Failed to grow buffer'
  • Mach異常
    • 先看下OSX和iOS的系統(tǒng)結構琢蛤,了解幾個基本概念



  • Mach的職責主要是進程和線程抽象蜓堕、虛擬內存管理、任務調度博其、進程間通信和消息傳遞機制等
  • BSD層則在Mach之上套才,提供一套可靠且更現(xiàn)代的API,提供了POSIX(可移植操作系統(tǒng)接口)兼容性慕淡。
  • Mach異常是指最底層的內核級異常,
  • Mach異常處理流程


  • BSD Signals
    • Mach已經(jīng)通過異常機制提供了底層的陷阱處理背伴,而BSD則在異常機制之上構建了信號處理機制。硬件產(chǎn)生的信號被Mach捕捉峰髓,然后轉換為對應的UNIX信號傻寂。為了維護一個統(tǒng)一的機制,操作系統(tǒng)和用戶嘗試的信號首先被轉換為Mach異常携兵,然后再轉換為信號(Signals)疾掰,如下圖所示:


  • 信號可以看做是對硬件異常跟軟件異常的封裝,需要處理的signals
static const int g_fatalSignals[] =
{
 SIGABRT,//調用abort生成的信號,有可能是NSException也有可能是Mach
 SIGBUS,//非法地址
 SIGFPE,//算術運算錯誤
 SIGILL,//執(zhí)行非法指令
 SIGPIPE,//進程間通信產(chǎn)生徐紧,通信管道破裂
 SIGSEGV,//非法訪問地址静檬,比如野指針,通常是對象的異常釋放并级,指針未清空
 SIGSYS,//非法的系統(tǒng)調用
 SIGTRAP,//斷點指令巴柿,一般出現(xiàn)在debug調試時
};
  • Mach exception和Signal轉換關系


3.crash收集

  • Objective-C uncaughtException可以通過NSSetUncaughtExceptionHandler系統(tǒng)回調進行捕獲
  • Mach異常,BSD將mach異常最終都轉換為信號異常死遭,所以我們只需要捕捉那些fatal signals广恢,如果開發(fā)者沒有捕獲Mach異常,則會被host層的方法ux_exception()將異常轉換為對應的UNIX信號呀潭,并通過方法threadsignal()將信號投遞到出錯線程钉迷。可以通過方法signal(x, SignalHandler)來捕獲single钠署。
  • C++ exceptions使用系統(tǒng)封裝好的函數(shù)std::set_terminate(CPPExceptionTerminate)來設置回調
  • 未被try catchNSException會發(fā)出killpthread_kill信號-> Mach異常-> Unix信號(SIGABRT),但是SIGABRT在處理收集信息時糠聪,獲取當前堆棧時獲取不到,所以采用NSSetUncaughtExceptionHandler,可以參考KSCrash 源碼

4.Crash快速分析

  • 當我們拿到crash日志時谐鼎,應首先從crash Type舰蟆,crash thread 快速定位到造成crash的代碼段。之所以首先要看這兩個,是因為type能大致知道crash的類型身害,如果是OC類型的異常味悄,那基本上處理起來比較簡單,如果是mach signals類型的塌鸯,通過查看造成crash的線程堆棧侍瑟,也能快速定位到方法,舉個實際項目中的例子:

線上有個偶現(xiàn)的crash丙猬,crash Type為SIGSEGV涨颜,且thread不定,子線程茧球,主線程都會存在庭瑰,但是代碼段相同,由于SIGSEGV是野指針異常類型抢埋,且由于在多線程中都會觸發(fā)见擦,說明問題基本上是多線程的對象讀寫安全問題

5.參考資料

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市羹令,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌损痰,老刑警劉巖福侈,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異卢未,居然都是意外死亡肪凛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門辽社,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伟墙,“玉大人,你說我怎么就攤上這事滴铅〈量” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵汉匙,是天一觀的道長拱烁。 經(jīng)常有香客問我,道長噩翠,這世上最難降的妖魔是什么戏自? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮伤锚,結果婚禮上擅笔,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好猛们,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布念脯。 她就那樣靜靜地躺著,像睡著了一般阅懦。 火紅的嫁衣襯著肌膚如雪和二。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天耳胎,我揣著相機與錄音惯吕,去河邊找鬼。 笑死怕午,一個胖子當著我的面吹牛废登,可吹牛的內容都是我干的。 我是一名探鬼主播郁惜,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼堡距,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了兆蕉?” 一聲冷哼從身側響起羽戒,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎虎韵,沒想到半個月后易稠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡包蓝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年驶社,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片测萎。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡亡电,死狀恐怖,靈堂內的尸體忽然破棺而出硅瞧,到底是詐尸還是另有隱情份乒,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布腕唧,位于F島的核電站冒嫡,受9級特大地震影響,放射性物質發(fā)生泄漏四苇。R本人自食惡果不足惜孝凌,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望月腋。 院中可真熱鬧蟀架,春花似錦瓣赂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捌省,卻和暖如春苫纤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纲缓。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工卷拘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人祝高。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓栗弟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親工闺。 傳聞我的和親對象是個殘疾皇子乍赫,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容

  • 目的 探索iOS Crash分類及捕獲流程 了解Crash文件結構及段含義 了解Mach-o文件結構 分析Cras...
    lltree閱讀 1,313評論 0 8
  • 摘錄:lltree Crash分類 Crash的主要原因是你的應用收到了未處理的信號。未處理信號可能來源于三個地方...
    NJ_墨閱讀 1,663評論 0 3
  • 最近在做 Crash 分析方面的工作陆蟆,發(fā)現(xiàn) iOS 的崩潰捕獲和堆棧符號化雖然已經(jīng)有很多資料可以參考雷厂,但是沒有比較...
    Joy___閱讀 15,191評論 15 142
  • Crash 日志從哪來?一般有 2 個渠道: 蘋果收集的 Crash 日志 用戶手機上 設置 -> 隱私 -> 分...
    M_慕宸閱讀 2,699評論 0 10
  • 異常分類 軟件異常(OC異常) 主要來源于 kill() 叠殷、 pthread_kill() 兩個 API 的調用,...
    conowen閱讀 2,203評論 1 1