日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

iOS之異常與信號使用場景分析_IOS

作者:好_好先生 ? 更新時間: 2022-12-23 編程語言

正文

Crash的主要原因是你的應(yīng)用收到了未處理的信號。 未處理的信號可能來源于三個地方:kernel(系統(tǒng)內(nèi)核)、其他進(jìn)程、以及App本身。 因此,crash異常也分為三種:

  • Mach異常:是指底層的內(nèi)核級異常。用戶態(tài)的開發(fā)者可以直接通過Mach API設(shè)置Thread、task、host的異常端口,來捕獲Mach異常。
  • Unix信號:又稱BSD信號,如果開發(fā)者沒有捕獲Mach異常,則會被host層的方法ux_exception()將異常轉(zhuǎn)換為對應(yīng)的UNIX信號,并通過方法threadsignal()將信號投遞到出錯的線程。可以通過方法singnal(x, SignalHandler)來捕獲single。
  • NSException:應(yīng)用級異常,它是未被捕獲的Objective-C異常,導(dǎo)致程序向自身發(fā)送了SIGABRT信號而崩潰,對于未捕獲的Objective-C異常,是可以通過try catch來捕獲的,或者通過NSSetUncaughtExceptionHandler()機(jī)制來捕獲。

異常

Exception Type:

異常的type固定是SIGABRT,其實是CrashReporter在捕獲Exception之后,再調(diào)用abort()發(fā)出的信號類型。這個機(jī)制也決定了如果是Exception Crash,堆棧就看這里的Last Exception Backtrace:, Crash Thread 里面固定是handleException的堆棧,沒有查看的意義。

Exception Codes:

一般就是 0 at 0x18ac2378,后面這個地址就是發(fā)生異常的對象的地址

特殊的 Exception Code

  • 0xdead10cc - Deaklock

我們在掛起之前持有文件鎖或 SQLite 數(shù)據(jù)庫鎖。我們應(yīng)該在掛起之前釋放鎖

  • 0xbaaaaaad - Bad

通過側(cè)面和兩個音量按鈕對整個系統(tǒng)進(jìn)行了 stackshot。

  • 0xbad22222 - Bad too (two) many times

可能是 VOIP 應(yīng)用被頻繁喚起導(dǎo)致的崩潰。也可以注意一下我們的后臺調(diào)用網(wǎng)絡(luò)的代碼。 如果我們的TCP連接被喚醒太多次(例如 300 秒內(nèi)喚醒 15 次),就會導(dǎo)致此崩潰。

  • 0x8badf00d - Ate (eight) bad food

我們的應(yīng)用程序執(zhí)行狀態(tài)更改(啟動、關(guān)閉、處理系統(tǒng)消息等)花費了太長時間。與看門狗的時間策略發(fā)生沖突(超時)并導(dǎo)致終止。最常見的罪魁禍?zhǔn)资窃谥骶€程上進(jìn)行同步的網(wǎng)絡(luò)連接。

  • 0xc00010ff - Cool Off

系統(tǒng)檢測的設(shè)備發(fā)燙而終止了我們的 App。如果只在少量設(shè)備上(幾個)發(fā)生,那就可能是由于硬件的問題,而不是我們 App 問題。但是如果發(fā)生在其他設(shè)備上,我們應(yīng)該使用 Instruments 去檢查我們 App 的耗電量問題。

  • 0x2bad45ec - Too bad for security

發(fā)生安全沖突。 如果 Termination Description 顯示為 Process detected doing insecure drawing while in secure mode,則意味著我們的應(yīng)用嘗試在不允許的情況下進(jìn)行繪制,例如在鎖定屏幕的情況下。

Triggered by Thread:

發(fā)生Crash的線程

Application Specific Infomation:

Exception的信息,這個是定位異常的關(guān)鍵信息

Last Exception Backtrace:

拋出異常的代碼堆棧,如果是異常,就看這個堆棧

主要信號

主要信號有 SIGTERM、SIGABRT、SIGSEGV、SIGBUS、SIGILL、SIGFPT、SIGKILL、SIGTRAP

程序結(jié)束(terminate)信號,與SIGKILL不同的是該信號可以被阻塞和處理。通常用來要求程序自己正常退出。iOS中一般不會處理到這個信號

SIGABRT原因

  • double free指針,void *ptr = malloc(256); free(ptr);free(ptr);// 重復(fù)釋放會導(dǎo)致SIGABRT錯誤
  • free沒有初始化的地址或者錯誤的地址,void ptr - (void)0x0000100; free(ptr);//釋放未初始化的地址導(dǎo)致SIGABRT錯誤
  • 內(nèi)存越界,char str2[10]; char *str1 = "askldfjadslfjsalkjfsalkfdj"; strcpy(str2, str1);
  • 直接調(diào)用abort()
  • 直接調(diào)用assert()

場景

全局變量賦值的代碼段,被多線程調(diào)用同時賦值,上一次賦的值就可能被多個線程釋放

解決方案

刪掉類似的賦值操作或者加鎖

SIGSEGV原因:

  • invalid memory access(segmentation fault)
  • 無效的內(nèi)存地址引用信號(常見的野指針訪問,訪問了沒有權(quán)限的內(nèi)存地址,系統(tǒng)內(nèi)存地址等)
  • 非ARC模式下,iOS中經(jīng)常會出現(xiàn)在Delegate對象野指針訪問
  • ARC模式下,iOS經(jīng)常會出現(xiàn)在Block代碼塊內(nèi)強(qiáng)持有可能釋放的對象

場景:

SDWebImageDownloaderOperation 生命周期的管理和錯誤回調(diào)是在2個queue, 有可能 self 已經(jīng)進(jìn)入釋放邏輯,再訪問 self.completeBlock, 再訪問就是無效的。

原因:

多線程訪問或者操作對象、棧溢出。

SIBBUS原因:

  • mmap 內(nèi)存映射訪問超出了??
char *p, tmp;
NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"txt"];
int fd = open(path.UTF8String, O_RDWR);
p = (char*)mmap(NULL,FILESIZE, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0); signal(SIGBUS, handle_sigbus);
getchar();
for(int i=0;i<FILESIZE;i++){
	tmp = p[i];
}
printf("ok\n");
  • 訪問未對?的內(nèi)存地址, int pi = (int)(0x00001111); *pi = 17;

場景:

mmap 映射了?個?件的內(nèi)存,寫入時越界。

對比:

SIGSGV 訪問的是?效的內(nèi)存,就是該內(nèi)存不屬于我們的進(jìn)程,或者沒有權(quán)限,SIGBUS指的是 CPU ?法操作該地址,?部分是沒有對?導(dǎo)致的。

SIGILL原因:

  • 執(zhí)??法指令
  • 堆棧溢出

典型場景:

iOS 上該問題有可能會隨機(jī)產(chǎn)?在任何動態(tài)庫、靜態(tài)庫的?法中,?旦出現(xiàn)之后,應(yīng)?會?直崩潰

解決方案:

app級別的代碼沒有修改可執(zhí)?段的權(quán)限,?法污染代碼段,判斷是蘋果增量的問題,用戶重啟?機(jī)

定義:

程序結(jié)束接收中?信號,?般exit()會發(fā)?這個信號,當(dāng)前應(yīng)用不能捕獲,也無法忽略,OOM,Watchdog最終都是這個異常信號。

  • ?時間占?太多 CPU 資源,被系統(tǒng)殺掉
  • 應(yīng)?啟動的時候,在主線程做?時間操作,或者卡死,導(dǎo)致被 watchdog 殺死
  • 線程切換過于頻繁,被系統(tǒng)殺掉
  • 應(yīng)?占?過多內(nèi)存,被 jetsam 殺掉

SIGTRAP原因:

很多系統(tǒng)庫例如 WebKit,libdispatch 等使?了__builtin_trap() ?法去觸發(fā)斷點異常,在debug 模式下,會觸發(fā)調(diào)試器斷點,這樣開發(fā)可以實時查看問題,在 release 模式下,應(yīng)?就會崩潰,然后產(chǎn)? SIGTRAP 信號。

典型場景:

dispatch_group_enter 和 dispatch_group_leave 調(diào)?不匹配,如果dispatch_group_leave 多調(diào)?了,會觸發(fā) DISPATCH_CLIENT_CRASH,在DISPATCH_CLIENT_CRASH 內(nèi)部會調(diào)?__builtin_trap() 觸發(fā)調(diào)式陷阱?。

Mach 異常

Mach異常的好處就是可以捕獲更多的Crash,?如循環(huán)遞歸導(dǎo)致的堆棧溢出crash。原本信號的?式回調(diào)會在崩潰的線程??,但是因為循環(huán)遞歸已經(jīng)堆棧溢出了,已經(jīng)沒有環(huán)境來執(zhí)?crash捕獲的邏輯了,但是Mach異常捕獲可以定義單獨的線程來處理Mach異常邏輯。 如何區(qū)分我們看到的?志是Mach異常的呢? Exception Type: 是EXC_打頭的話,就是Mach異常了,后?的Exception Subtype:其實是根據(jù)Exception Type:轉(zhuǎn)了?下

Exception Type:

  • EXC_BAD_ACCESS:內(nèi)存不能訪問,對應(yīng)SIGBUS和SIGSEGV
  • EXC_BAD_INSTRUCTION:?法的指令,對應(yīng)捕獲到的SIGILL問題
  • EXC_ARITHMETIC:算術(shù)運(yùn)算出錯,對應(yīng)SIGFPE
  • EXC_EMULATION:對應(yīng)SIGEMT
  • EXC_SOFTWARE:軟件出錯,對應(yīng)SIGSYS,SIGPIPE,SIGABRT,SIGKILL
  • EXC_BREAKPOINT:對應(yīng)SIGTRAP
  • EXC_SYSCALL:不常?
  • EXC_MACH_SYSCALL:不常?
  • EXC_RPC_ALERT:不常?
  • EXC_CRASH:對應(yīng)SIGBART
  • EXC_GUARD:?般是?件句柄防護(hù),?如close到了?個內(nèi)核的fd.
  • EXC_RESOURCE:遇到了?些系統(tǒng)資源的限制,?般是CPU過載,線程調(diào)度太頻繁,?如iOS中每秒?線程喚醒次數(shù)不能超過150

Abort

Abort 包含哪些場景?

  • 內(nèi)存使?量過?、短時間內(nèi)申請?量內(nèi)存,系統(tǒng)發(fā)送signal9(signal9?法通過信號捕獲)強(qiáng)制殺死進(jìn)程(類似于Android端上的OOM),就是?家常說的Jetsam事件
  • 主線程發(fā)?卡死超過?定時間watchdog強(qiáng)制殺死進(jìn)程(不同系統(tǒng)版本卡死時間不同)
  • 啟動超時、后臺切前臺resume超時
  • 部分死循環(huán)、遞歸等造成的棧溢出

Abort目標(biāo)

  • 現(xiàn)場及上下?捕獲
  • 定位 Abort 的業(yè)務(wù)場景、發(fā)?原因
  • 基于現(xiàn)場及上下?捕獲數(shù)據(jù)、Abort發(fā)?原因的?法形成?效的?具鏈,?于快速定位線上崩潰率發(fā)?的主因

Abort推導(dǎo)規(guī)則

需要根據(jù)可能導(dǎo)致客戶端崩潰的原因設(shè)計推導(dǎo)規(guī)則,并基于線上?戶的 Abort 數(shù)據(jù)快速聚合,從而發(fā)現(xiàn)并解決影響線上穩(wěn)定性的問題

原文鏈接:https://juejin.cn/post/7169193114844790791

欄目分類
最近更新