理解 iOS Crash

作為一名開發(fā)人員,如何定位解決線上Crash是每一個必修的課題搂蜓。那問題來了,Crash 如何產(chǎn)生无畔?作為一名 iOS 開發(fā),我今天主要分享 iOS Crash 相關(guān)的內(nèi)容

Crash 產(chǎn)生

Crash 產(chǎn)生一般分兩種情況:

  1. 應(yīng)用程序自己調(diào)用退出函數(shù)吠冤。eg:調(diào)用自殺函數(shù) kill()
  2. 系統(tǒng)把你應(yīng)用殺死浑彰。eg:應(yīng)用內(nèi)存占用過高時,系統(tǒng)保護機制會把你的應(yīng)用干掉拯辙。

(各種崩潰場景后續(xù)再討論)
想清楚以上兩個場景之后我們我們來看幾個元兇郭变。

  • 軟件異常
    軟件異常主要來源于兩個 API 的調(diào)用 kill() 、 pthread_kill() , 而 iOS 中我們常常遇到的 NSException 未捕獲涯保、 abort() 函數(shù)調(diào)用等诉濒,都屬于這種情況。比如我們诚Υ海看到 Crash 堆棧中有 pthead_kill 方法的調(diào)用未荒。
    (此刻我知道你的內(nèi)心活動,**從來沒掉過啊及志。沒錯你是沒掉片排,但是系統(tǒng)庫會 eg:libc,刺激不刺激速侈,驚喜不驚喜)
  • 硬件異常
    硬件產(chǎn)生的信號始于處理器 trap率寡,處理器 trap 是平臺相關(guān)的。出現(xiàn)這種情況倚搬,計算機會暫停當(dāng)前程序勇劣,及時轉(zhuǎn)入故障處理。比如我們遇到的野指針崩潰大部分是硬件異常潭枣。
  • Mach異常
    這里雖然叫異常比默,但是要和上面的兩種分開來看。我們了解到蘋果的內(nèi)核 xnu 的核心是 Mach , 在 Mach 之上建立了 BSD 層盆犁∶溃“Mach異常” 是 “Mach異常處理流程” 的簡稱谐岁。不懂沒事醋奠,后面有講解

除了以上三個大殺器,還有一個是程序語言異常伊佃,這個在我們的Crash日志也是比較常見的窜司,但是與以上三個不同,這種異常往往是我們代碼邏輯不合理造成的航揉。沒錯塞祈,說的就是看文章的你,為啥會崩潰帅涂,你心里一點數(shù)都沒有嗎议薪?尤蛮??斯议?這種稍后我也會給大家總結(jié)

接下來我們看一下 Mac OS & iOS 是如何處理這些異常的产捞。以下內(nèi)容來自“深入解析 Mac OS X & iOS 操作系統(tǒng)”
軟件異常處理:

軟件信號處理流程

硬件異常處理:
硬件信號處理流程

通過上面兩張圖,我們可以很清楚的看到哼御,無論是軟件異常坯临,還是硬件異常,最終都會被轉(zhuǎn)換為信號恋昼,然后通過act_set_astbsd()發(fā)送給我們的應(yīng)用進程尿扯,喚醒其中的某個線程響應(yīng)指定操作(記住這句話,我們后續(xù)有大用)焰雕。此時的信號是 UNIX 信號,如 SIGBUS SIGSEGV SIGABRT SIGKILL 等芳杏。此時大家可以去翻翻后臺的Crash日志矩屁,你會發(fā)現(xiàn)好多這中以SIG開頭的Crash。具體信號的含義大家可以自行 Google爵赵,或者直接點擊文章參考參考查看吝秕。

UNIX信號拋出簡單流程大致如下:

Unix 信號產(chǎn)生.jpeg

附 “Mach異常” 與 “UNIX信號” 的轉(zhuǎn)換關(guān)系代碼空幻,來自 xnu 中的 bsd/uxkern/ux_exception.c :

switch(exception) {
case EXC_BAD_ACCESS:
    if (code == KERN_INVALID_ADDRESS)
        *ux_signal = SIGSEGV;
    else
        *ux_signal = SIGBUS;
    break;

case EXC_BAD_INSTRUCTION:
    *ux_signal = SIGILL;
    break;

case EXC_ARITHMETIC:
    *ux_signal = SIGFPE;
    break;

case EXC_EMULATION:
    *ux_signal = SIGEMT;
    break;

case EXC_SOFTWARE:
    switch (code) {

    case EXC_UNIX_BAD_SYSCALL:
    *ux_signal = SIGSYS;
    break;
    case EXC_UNIX_BAD_PIPE:
    *ux_signal = SIGPIPE;
    break;
    case EXC_UNIX_ABORT:
    *ux_signal = SIGABRT;
    break;
    case EXC_SOFT_SIGNAL:
    *ux_signal = SIGKILL;
    break;
    }
    break;

case EXC_BREAKPOINT:
    *ux_signal = SIGTRAP;
    break;
}

看了以上內(nèi)容烁峭,我想你的內(nèi)心一定是

你不要再說了

老實說以上理解以上內(nèi)容確實需要你有相當(dāng)?shù)挠嬎銠C基礎(chǔ)功力才行,為了照顧你的心情秕铛,接下來咱們聊點你能看懂的约郁。
除了上面咱們說道的,還有一種程序語言異常但两,這種異常通常是程序語言自己封裝好的鬓梅。產(chǎn)生的原因通常是因為程序員編寫邏輯錯誤造成的,沒錯谨湘,就是你自己造的孽绽快。作為iOS程序員,我們主要是關(guān)注的是 Objec-C 和 Swift紧阔。
Object-C 的異常的異常主要是NSException對象封裝的坊罢,比較多,咱們這里看幾個比較常見的擅耽,文末有參考中有鏈接大家可以看到所有的異常類型活孩。
先來個王炸,這個你肯定見過:

  1. NSInvalidArgumentException
    傳遞非法參數(shù)給一個方法時拋出的異常乖仇。
    常見場景:

    • NSNutableDictionaryr操作key或value的函數(shù)诱鞠,如setObject:forKey:挎挖、removeObjectForKey等等。
    • NSMutableArray操作value的函數(shù)航夺,如addObject:蕉朵、 insertObject:atIndex:等等。
    • NSString操作函數(shù)阳掐,如initWithString:始衅、initWithFormat:、stringWithString:等等缭保。

    這里要住意多線程操作汛闸,這個坑,深到一半人爬不出來艺骂,比如我前面的小朋友诸老,直接被搞離職了

  2. NSRangeException:
    嘗試訪問某些數(shù)據(jù)范圍之外時拋出的異常。
    常見場景:

    • NSArray包含索引的操作钳恕,如insertObject:atIndex:别伏、objectAtIndex:等等。
    • NSString包含索引的操作忧额,如characterAtIndex:厘肮、getCharacters:range:等等。
  3. NSFileHandleOperationException
    如果嘗試確定文件句柄類型失敗或嘗試讀取文件或通道失敗睦番,則會拋出此異常类茂。
    常見場景:

    • 空間不足:會提示No space left on devie。
    • 沒有讀寫權(quán)限:會提示Bad file descriptor托嚣。
    • 讀文件失敗巩检。

    在操作文件時,要驗證文件句柄的有效性示启,對文件大小進行校驗碴巾,對存儲空間進行判斷。

  4. KVO引起的異常:
    常見場景:

    • 多次移除KVO
      拋出NSRangeException異常
    • 添加或移除時keyPath參數(shù)為nil
    • 沒有實現(xiàn)observeValueForKeyPath方法(非必顯丑搔, iOS14)

    我在當(dāng)前 iOS 15的系統(tǒng)測試過厦瓢,無論是沒有移除觀察者還是VC推出時沒有一處觀察者都沒出現(xiàn)崩潰。多次移除相同Path時和path名字為nil會出現(xiàn)Crash

  5. iOS Crash之NSMallocException
    常見場景:

    • 分配的空間過大
    • 圖像占用空間過大
    • OOM問題啤月。這個主要是程序死循環(huán)造成的
  6. NSGenericException
    常見場景:

    • 可變對象遍歷過程中發(fā)生了改變煮仇。

以上大概就是我們開發(fā)和線上應(yīng)用常見一些異常。至于swift谎仲,應(yīng)為NSexception是Cocoa框架的浙垫,swift也繞不過,所以上面的異常,swift也是都有的夹姥,當(dāng)然由于語言上的設(shè)計優(yōu)勢杉武,swift出現(xiàn)的可能行降低一些。swift 該只有 try! 解析空辙售。其他歡迎大家補充轻抱。
畢竟是初始 iOS Crash,就給大家分析到這里吧旦部,下一篇我們看一下crash收集和符號化祈搜。

參考文檔:
處理器陷阱
UNIX 信號
iOS Crash 分析策略
野指針
理解異常類型
Object-C Exception
iOS內(nèi)功篇:淺談Crash

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末士八,一起剝皮案震驚了整個濱河市容燕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌婚度,老刑警劉巖蘸秘,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蝗茁,居然都是意外死亡醋虏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門评甜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人仔涩,你說我怎么就攤上這事忍坷。” “怎么了熔脂?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵佩研,是天一觀的道長。 經(jīng)常有香客問我霞揉,道長旬薯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任适秩,我火速辦了婚禮绊序,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秽荞。我一直安慰自己骤公,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布扬跋。 她就那樣靜靜地躺著阶捆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上洒试,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天倍奢,我揣著相機與錄音,去河邊找鬼垒棋。 笑死卒煞,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捕犬。 我是一名探鬼主播跷坝,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼碉碉!你這毒婦竟也來了柴钻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤垢粮,失蹤者是張志新(化名)和其女友劉穎贴届,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜡吧,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡毫蚓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了昔善。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片元潘。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖君仆,靈堂內(nèi)的尸體忽然破棺而出翩概,到底是詐尸還是另有隱情,我是刑警寧澤返咱,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布钥庇,位于F島的核電站,受9級特大地震影響咖摹,放射性物質(zhì)發(fā)生泄漏评姨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一萤晴、第九天 我趴在偏房一處隱蔽的房頂上張望吐句。 院中可真熱鬧,春花似錦店读、人聲如沸蕴侧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽净宵。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間择葡,已是汗流浹背紧武。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留敏储,地道東北人阻星。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像已添,于是被迫代替她去往敵國和親妥箕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容