問題:有哪些常見的 Crash 場景?

常見的 Crash 場景

  • 訪問了僵尸對象
  • 訪問了不存在的方法unrecognized selector sent to instance
  • 數(shù)組越界
  • 在定時器下一次回調(diào)前將定時器釋放,會Crash
  • KVC造成的crash
  • EXC_BAD_ACCESS
  • KVO引起的崩潰
  • 多線程中的崩潰
  • Socket長連接,進入后臺沒有關(guān)閉
  • Watch Dog超時造成的crash

什么時候會報 unrecognized selector 異常

當調(diào)用對象(子類,各級父類)中不含有對應(yīng)方法的時候,并且依舊沒有給出“消息轉(zhuǎn)發(fā)”的具體方案的時候,程序在運行時會crash并拋出 unrecognized selector 異常
OC 中的每個方法在運行時會被轉(zhuǎn)為消息發(fā)送objc_msgSend(reciver, selector)
例如 [person say]就會被轉(zhuǎn)化為 objc_msgSend(person, @selector(say))
運行時會根據(jù)對象(reciever) 的isa 指針找到該對象所對應(yīng)的類,然后會依次在對應(yīng)的 類,父類,爺爺類,根類中找對應(yīng)的方法

下面講述對象方法的解析過程:

  • 第一步:+(BOOL)resolveInstanceMethod:(SEL)sel``實現(xiàn)方法,指定是否動態(tài)添加方法。 若返回NO,則進入下一步,若返回YES,則通過class_addMethod`函數(shù)動態(tài)地添加方 法,消息得到處理,此流程完畢。
  • 第二步:在第一步返回的是NO時,就會進入- (id)forwardingTargetForSelector:(SEL)aSelector方法,這是運行時給我們的第二次機會,用于指定哪個對象響應(yīng)這個selector。不能指定為self。若返回nil,表示沒有響應(yīng) 者,則會進入第三步。若返回某個對象,則會調(diào)用該對象的方法。
  • 第三步:若第二步返回的是nil,則我們首先要通過- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector指定方法簽名,若返回nil,則表示不處 理。若返回方法簽名,則會進入下一步。
  • 第四步:當?shù)谌椒祷胤椒ǚ椒ê灻螅蜁{(diào)用- (void)forwardInvocation:(NSInvocation *)anInvocation方法,我們可以通過anInvocation 對象做很多處理,比如修改實現(xiàn)方法,修改響應(yīng)對象等
  • 第五步:若沒有實現(xiàn)- (void)forwardInvocation:(NSInvocation *)anInvocation方法,那么 會進入- (void)doesNotRecognizeSelector:(SEL)aSelector方法。若我們沒有實現(xiàn)這個方 法,那么就會crash,然后提示打不到響應(yīng)的方法。到此,動態(tài)解析的流程就結(jié)束了。

數(shù)組越界

在數(shù)組取值時加判斷

if array.count > index {
   let value = array[index]
}

KVC造成的crash

給不存在的key(包括key為nil)設(shè)置value

關(guān)于EXC_BAD_ACCESS

出現(xiàn)的原因: 訪問了野指針, 比如訪問已經(jīng)釋放對象的成員變量或者發(fā)消息, 死循環(huán)等;
解決方法:

  • 重寫對象的respondsToSelector 方法, 先找到出現(xiàn) EXECBADACCESS 前訪問的最后一個 object;

  • 設(shè)置Enable Zombie Objects;
    Zombie
  • 設(shè)置全局斷點快速定位問題代碼所在行,接收所有異常;

  • Xcode7 之后已經(jīng)集成了 BAD_ACCESS 捕獲功能: Address Sanitizer 與步驟 2 一樣設(shè)置;
    Address Sanitizer
  • analyze(靜態(tài)分析, 不一定管用)

如何解決很難復(fù)現(xiàn)的crash

  • 1.有錯誤日志先看錯誤日志信息
  • 2.沒有錯誤日志,第一步分析函數(shù)中的所有分支, 是否在語法上存在可能缺少條件的問題.所以檢查所以的分支,確保每個分支執(zhí)行的結(jié)果是正確的.
  • 3.檢查函數(shù)的參數(shù),保證必傳參數(shù)不能為空,若為空應(yīng)該拋出異常,因此用斷言檢查參數(shù)的正確性很重要
  • 4.檢查函數(shù)中每個分支所調(diào)用的函數(shù)返回結(jié)果是正確的,其實就是遞歸過程(重復(fù)2,3步驟)

KVO引起的崩潰

  • 觀察者是局部變量,會崩潰
  • 被觀察者是局部變量,會崩潰
  • 沒有實現(xiàn)observeValueForKeyPath:ofObject:changecontext:方法:,會崩潰
  • 重復(fù)移除觀察者,會崩潰
  • 重復(fù)添加觀察者,不會崩潰,但是添加多少次,一次改變就會被觀察多少次

多線程中的崩潰

多線程遇到需要同步的時候,加鎖,添加信號量等進行同步操作。一般多線程發(fā)生的Crash,會收到SIGSEGV信號,表明試圖訪問未分配給自己的內(nèi)存, 或試圖往沒有寫權(quán)限的內(nèi)存地址寫數(shù)據(jù)。

  • 死鎖、子線程中更新UI、多個線程同時釋放一個對象
  • 在子線程中更新UI
  • dispatch_group crash,dispatch_group_leave的次數(shù)比dispatch_group_enter次數(shù)多
  • 多線程下非線程安全類的使用,如NSMutableArrayNSMutableDictionary。NSCache是線程安全的。
  • 數(shù)據(jù)緩存到磁盤和讀取。

Socket長連接,進入后臺沒有關(guān)閉

當服務(wù)器close一個連接時,若client端接著發(fā)數(shù)據(jù)。根據(jù)TCP協(xié)議的規(guī)定,會收到一個RST響應(yīng),client再往這個服務(wù)器發(fā)送數(shù)據(jù)時,系統(tǒng)會發(fā)出一個SIGPIPE信號給進程,告訴進程這個連接已經(jīng)斷開了,不要再寫了。而根據(jù)信號的默認處理規(guī)則,SIGPIPE信號的默認執(zhí)行動作是terminate(終止、退出),所以client會退出。
長連接socket或重定向管道進入后臺,沒有關(guān)閉導致崩潰的解決辦法:

  • 切換到后臺是,關(guān)閉長連接和管道,回到前臺重新創(chuàng)建。
  • 使用signal(SIGPIPE,SIG_IGN),將SIGPIP交給系統(tǒng)處理,這么做將SIGPIPE設(shè)為SIG_IGN,使客戶端不執(zhí)行默認操作,即不退出。

Watch Dog超時造成的crash

主線程執(zhí)行耗時操作,導致主線程被卡超過一定時間。一般異常編碼是0x8badf00d,表示應(yīng)用發(fā)生watch dog超時而被iOS終止,通常是應(yīng)用花費太多的時間無法啟動、終止或者響應(yīng)系統(tǒng)事件。
解決:主線程只負責更新UI和事件響應(yīng),將耗時操作(網(wǎng)絡(luò)請求、數(shù)據(jù)庫讀寫等)異步放到后臺線程執(zhí)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 訪問了僵尸對象 訪問野指針 訪問了不存在的方法 數(shù)組越界 在定時器下一次回調(diào)前將定時器釋放
    iOS_Alex閱讀 553評論 0 0
  • 我們常常會聽說 Objective-C 是一門動態(tài)語言,那么這個「動態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,333評論 0 7
  • iOS 面試題總結(jié)(一) 101. 修改下面的代碼: typedef enum{ UserSex_Man,User...
    AlaricMurray閱讀 1,838評論 0 6
  • 前言: 關(guān)于Runtime的資料網(wǎng)上一搜很多,但總是寫的只言片語,不太全面。最近花了一個星期的時間重新學習Runt...
    小霍同學閱讀 646評論 0 0
  • 我們家長,希望孩子在以后的日子里能夠更好地適應(yīng)學校,社會的節(jié)奏,能夠更加獨立,擁有好的人緣,那么我們家長就要及時地...
    龍清風閱讀 400評論 1 2

友情鏈接更多精彩內(nèi)容