iOS開發(fā)-分析生產(chǎn)環(huán)境的Crash

前言

APP 的 Crash 一般會定位為嚴重問題聂渊,生產(chǎn)環(huán)境下的 APP 一般需要做到 Crash 率高于 99.8%。真實的生產(chǎn)環(huán)境可能十分復(fù)雜劝堪,可能存在極其惡劣的網(wǎng)絡(luò)環(huán)境的影響墓怀,后臺傳輸數(shù)據(jù)格式不準確,內(nèi)存處理不當?shù)忍浚@些都可能引發(fā) APP 的 Crash炼七。開發(fā)環(huán)境下,很難做到完全容錯布持,測試也幾乎不可能覆蓋所有場景豌拙。因此,行之有效的監(jiān)測機制幾乎是必然的题暖。

Objective-C 的不安全性

在 Objective-C 中姆蘸,有些數(shù)據(jù)結(jié)構(gòu)或方法只能接收非空的值,如果我們在調(diào)用這些方法時芙委,沒有做好充分的判斷交汤,錯誤的傳入一個空值,這時候編譯階段并不會給出警告细溅,在程序的運行時才會直接崩潰卖陵。類似于這段代碼:

NSData *data = [NSJSONSerialization dataWithJSONObject:array options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:(NSUTF8StringEncoding)];

在上述代碼中,當變量 array == nil 時侧啼,程序即會崩潰牛柒。這類問題在開發(fā)中一般是由于數(shù)據(jù)的改變,沒有做足夠的容錯處理痊乾。如果測試的覆蓋率不全皮壁,極有可能在線上發(fā)生崩潰。

在 Swift 中哪审,在給上述方法傳入 array 之前蛾魄,需要對 array 做出明確的為空判斷, 否則編譯器會直接告警湿滓,一般會采用可選綁定(if...let)的形式對可選類型做判斷滴须,當能進入到對應(yīng)的代碼塊,也就意味著 array 一定是有值的叽奥。

let array : [Any]? = ["Alex"]
if let array = array {
    let data = try? JSONSerialization.data(withJSONObject: array, options: JSONSerialization.WritingOptions.prettyPrinted)
}

Swift 可以通過自身的一些語言特性讓這些問題避免在開發(fā)階段扔水,但是 Objective-C 很難做到。對于 Objective-C 開發(fā)的程序朝氓,非常有必要做一定的 Crash 監(jiān)聽工作魔市。當監(jiān)聽到這些信息之后主届,可以通過版本迭代或 HotPatch 的形式及時作出修復(fù),避免用戶的流失待德。

在我們的項目中應(yīng)用的是 友盟統(tǒng)計日志+dYSM分析工具 的形式岂膳,可以有效的解決一部分 Carsh。友盟統(tǒng)計只需要引入較少的代碼磅网,并在合適的時機調(diào)用極少的代碼谈截,無侵入性,容易移除涧偷。

友盟統(tǒng)計Crash日志

友盟統(tǒng)計具有分析流量來源簸喂、用戶屬性、行為數(shù)據(jù)燎潮、錯誤分析等特性喻鳄,在我們的產(chǎn)品中一般會接入用來統(tǒng)計程序的Crash日志。

上線的 APP 集成了友盟統(tǒng)計后确封,當發(fā)生崩潰時除呵,會在友盟統(tǒng)計后臺的錯誤分析模塊監(jiān)聽到崩潰日志。一般會看到兩種錯誤類型:

1. 明確指出了報錯API

*** +[NSJSONSerialization dataWithJSONObject:options:error:]: value parameter is nil
(null)
((
    0   CoreFoundation                      0x2268f933 <redacted> + 150
    1   libobjc.A.dylib                     0x21e2ae17 objc_exception_throw + 38
    2   CoreFoundation                      0x2268f861 <redacted> + 0
    3   Foundation                          0x22f28341 <redacted> + 84
    4   fuzhuxian                           0x80099 fuzhuxian + 508057
    5   UIKit                               0x27060bd9 <redacted> + 68
    6   UIKit                               0x27061283 <redacted> + 30
    7   UIKit                               0x26f577e3 <redacted> + 1230
    8   UIKit                               0x26f5aa85 <redacted> + 192
    9   UIKit                               0x26d38157 <redacted> + 90
    10  UIKit                               0x26c45ba5 <redacted> + 540
    11  UIKit                               0x26c45685 <redacted> + 204
    12  UIKit                               0x26c4557f <redacted> + 78
    13  QuartzCore                          0x24ca5689 <redacted> + 252
    14  libdispatch.dylib                   0x221fd80f <redacted> + 22
    15  libdispatch.dylib                   0x2220bba9 <redacted> + 1524
    16  CoreFoundation                      0x22651b6d <redacted> + 8
    17  CoreFoundation                      0x22650067 <redacted> + 1574
    18  CoreFoundation                      0x2259f229 CFRunLoopRunSpecific + 520
    19  CoreFoundation                      0x2259f015 CFRunLoopRunInMode + 108
    20  GraphicsServices                    0x23b8fac9 GSEventRunModal + 160
    21  UIKit                               0x26c73189 UIApplicationMain + 144
    22  fuzhuxian                           0x29af9 fuzhuxian + 154361
    23  libdyld.dylib                       0x22247873 <redacted> + 2
)

dSYM UUID: 679C384A-0751-3B66-8BAC-FB0DB78AC7B6
CPU Type: armv7
Slide Address: 0x00004000
Binary Image: fuzhuxian
Base Address: 0x0004b000

這一類的 Crash 明確的指出了崩潰的方法爪喘,上圖中的問題是 NSJSONSerialization 對象的 dataWithJsonObject 方法傳入了一個為空的參數(shù)颜曾,并且列出了報錯的內(nèi)存地址。類似的會打印出具體報錯API的還有數(shù)組越界問題等秉剑。

2. Application received signal SIGSEGV

Application received signal SIGSEGV
(null)
((
    0   CoreFoundation                      0x21b47933 <redacted> + 150
    1   libobjc.A.dylib                     0x212e2e17 objc_exception_throw + 38
    2   CoreFoundation                      0x21b47861 <redacted> + 0
    3   fuzhuxian                           0x362d87 fuzhuxian + 3534215
    4   libsystem_platform.dylib            0x2187606f _sigtramp + 34
    5   Foundation                          0x22365af5 __NSFireDelayedPerform + 468
    6   CoreFoundation                      0x21b0a58f <redacted> + 14
    7   CoreFoundation                      0x21b0a1c1 <redacted> + 936
    8   CoreFoundation                      0x21b0800d <redacted> + 1484
    9   CoreFoundation                      0x21a57229 CFRunLoopRunSpecific + 520
    10  CoreFoundation                      0x21a57015 CFRunLoopRunInMode + 108
    11  GraphicsServices                    0x23047ac9 GSEventRunModal + 160
    12  UIKit                               0x2612b189 UIApplicationMain + 144
    13  fuzhuxian                           0x29c41 fuzhuxian + 154689
    14  libdyld.dylib                       0x216ff873 <redacted> + 2
)

dSYM UUID: 27C7888F-E1F2-33DE-96ED-6031F25C66EC
CPU Type: armv7
Slide Address: 0x00004000
Binary Image: fuzhuxian
Base Address: 0x000f0000

這一類問題沒有指出具體報錯的方法泛豪,但是給出了可用來分析的內(nèi)存地址 0x362d870x29c41。出現(xiàn)這種問題的原因一般是程序訪問了無效的內(nèi)存侦鹏。

實際上僅僅有這些報錯的 API 或者 16 進制內(nèi)存地址意義不大诡曙,因為依然不能反應(yīng)出代碼中的哪一個文件的哪一列出了錯誤。為了找出崩潰的具體位置略水,需要借助 dYSM 文件進行分析价卤。

dYSM文件

dSYM 是保存 16 進制函數(shù)地址映射信息的中轉(zhuǎn)文件,我們調(diào)試的 symbols 都會包含在這個文件中渊涝,并且每次編譯項目的時候都會生成一個新的 dSYM 文件慎璧,位于 /Users/<用戶名>/Library/Developer/Xcode/Archives 目錄下。Xcode 編譯項目后會看到一個同名的 dSYM 文件驶赏。

每一個 xx.app 和 xx.app.dSYM 文件都有對應(yīng)的 UUID炸卑,crash 文件也有自己的 UUID既鞠,只要這三個文件的 UUID 一致煤傍,我們就可以通過他們解析出正確的錯誤函數(shù)信息了。因此嘱蛋,對于每一個發(fā)布版本我們都很有必要保存對應(yīng)的 Archives 文件 蚯姆。

dSYM分析工具

我們的項目中用到了 dSYMTools 作為分析工具分析 dSYM 文件五续,源碼可以直接編譯成 Mac APP。它的優(yōu)點在于直接面向 .xcarchive 文件進行分析龄恋,不需要再去找對應(yīng)的 dSYM 文件疙驾,系統(tǒng)會自動找到對應(yīng)的 dSYM 文件。

dSYMTools.png

可以直接將 achieve 出來的 .xcarchive 文件直接拖入到文件選擇區(qū)域郭毕,選擇對應(yīng)的 CPU 類型(一般 iPhone5S 和 iPad Air 之后的是 arm64 類型)它碎,工具會默認匹配出可執(zhí)行文件的 UDID 和 默認 Slide Address,只需要再鍵入報錯的內(nèi)存地址显押,如上文代錯誤內(nèi)存代碼中的 0x80099 0x29af9 0x362d87 0x29c41扳肛,點擊分析,即可打印出可能出錯的地方乘碑。

總結(jié)

對于每一個發(fā)布版本我們都很有必要保存對應(yīng)的 Archives 文件 挖息,這個文件記錄了
APP 的關(guān)鍵信息,可以作為日后分析問題的重要途徑兽肤。

在生產(chǎn)環(huán)境下通過集成友盟或其他 SDK 的形式監(jiān)測 Crash 報告套腹,這實際是一種滯后的監(jiān)聽機制,它并不能實時的改變代碼资铡、修復(fù)線上 Bug电禀,但是可以提升程序員的信心。對于開發(fā)者來說不失是一種有效的解決問題的方法笤休。

Swift 可以在開發(fā)階段有效的避免很大一部分上述問題 Xcode 自動的提示節(jié)省了一大部分思考的時間鞭呕,讓我們和你專注于業(yè)務(wù)邏輯的處理上,又保證了安全性宛官,這對于開發(fā)者而言無非是一件好事葫松。當然在寫 Objective-C 時,基本的風(fēng)險預(yù)估和容錯處理也必不可少底洗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腋么,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子亥揖,更是在濱河造成了極大的恐慌珊擂,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件费变,死亡現(xiàn)場離奇詭異摧扇,居然都是意外死亡,警方通過查閱死者的電腦和手機挚歧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門扛稽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人滑负,你說我怎么就攤上這事在张∮煤” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵帮匾,是天一觀的道長啄骇。 經(jīng)常有香客問我,道長瘟斜,這世上最難降的妖魔是什么缸夹? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮螺句,結(jié)果婚禮上明未,老公的妹妹穿的比我還像新娘。我一直安慰自己壹蔓,他們只是感情好趟妥,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著佣蓉,像睡著了一般披摄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勇凭,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天疚膊,我揣著相機與錄音,去河邊找鬼虾标。 笑死寓盗,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的璧函。 我是一名探鬼主播傀蚌,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蘸吓!你這毒婦竟也來了善炫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤库继,失蹤者是張志新(化名)和其女友劉穎箩艺,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宪萄,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡艺谆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拜英。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片静汤。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出撒妈,到底是詐尸還是另有隱情恢暖,我是刑警寧澤排监,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布狰右,位于F島的核電站,受9級特大地震影響舆床,放射性物質(zhì)發(fā)生泄漏棋蚌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一挨队、第九天 我趴在偏房一處隱蔽的房頂上張望谷暮。 院中可真熱鬧,春花似錦盛垦、人聲如沸湿弦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颊埃。三九已至,卻和暖如春蝶俱,著一層夾襖步出監(jiān)牢的瞬間班利,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工榨呆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罗标,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓积蜻,卻偏偏與公主長得像闯割,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子竿拆,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

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