扒蟲篇-崩潰日志解讀及Crash收集

Paste_Image.png

前言

崩潰是讓發(fā)人員比較頭痛的事情,app崩潰了,說明代碼寫的有問題叼风,這時(shí)如何快速定位到崩潰的地方很重要。調(diào)試階段是比較容易找到出問題的地方的棍苹,但是已經(jīng)上線的app并分析崩潰報(bào)告就比較麻煩了无宿。最終,我們可以通過iOS崩潰日志在大多數(shù)情況下枢里,你能從中了解到關(guān)于閃退的詳盡孽鸡、有用的信息。線上崩潰可以通過 iTunesConnect 中心的Cash收集栏豺,也可以通過第三方Cash收集工具彬碱,亦或自己在工程中手動(dòng)收集崩潰日志上傳到服務(wù)器中,本文做個(gè)小結(jié)奥洼,希望對(duì)初入者能有些幫助巷疼。

崩潰

崩潰是由于程序拋出異常,系統(tǒng)異常結(jié)束的一種現(xiàn)象灵奖。我們可以先了解一下異常 NSException嚼沿,這對(duì)于我們理解崩潰有幫助。NSException掌控著程序的生命瓷患,程序的崩潰就是NSException來控制的骡尽。其實(shí)主要的出發(fā)點(diǎn)是讓開發(fā)者認(rèn)識(shí)到哪里的代碼有問題。

** NSException**

這個(gè)樣子

其實(shí)控制臺(tái)輸出的日志信息就是NSException產(chǎn)生的擅编,一旦程序拋出異常爆阶,程序就會(huì)崩潰,控制臺(tái)就會(huì)有這些崩潰日志沙咏。

下面代碼就會(huì)讓你的程序崩潰(下面代碼出自別人的文章辨图,文末有原文出處)

//異常的名稱   
NSString *exceptionName = @"自定義異常";   
//異常的原因    
NSString *exceptionReason = @"我長得太帥了,所以程序崩潰了";    
//異常的信息   
NSDictionary *exceptionUserInfo = nil; 
NSException *exception = [NSException exceptionWithName:exceptionName reason:exceptionReason userInfo:exceptionUserInfo];       
NSString *aboutMe = @"太帥了";      
if ([aboutMe isEqualToString:@"太帥了"])     
{   //拋異常        
  @throw exception;    
}

崩潰截圖如下

1478827158887712.png

NSException的實(shí)用技巧

  • 1肢藐、 若自己封裝一套SDK故河,若要提示哪里出錯(cuò),那么就可以使用NSException吆豹。就像上面NSException的基本用法中的代碼一樣鱼的。

  • 2理盆、可以用來捕獲異常,防止程序的崩潰凑阶。當(dāng)你意識(shí)到某段代碼可能存在崩潰的危險(xiǎn)猿规,那么你就可以通過捕獲異常來防止程序的崩潰。代碼如下

    @try {        
      //如果@try中的代碼會(huì)導(dǎo)致程序崩潰宙橱,就會(huì)來到@catch
      //將一個(gè)nil插入到可變數(shù)組中姨俩,這行代碼肯定有問題
      [arrayM addObject:nilStr];
     }    
    @catch (NSException *exception) {        
      //如果@try中的代碼有問題(導(dǎo)致崩潰),就會(huì)來到@catch
      //在這里你可以進(jìn)行相應(yīng)的處理操作
      //如果你要拋出異常(讓程序崩潰),就寫上 @throw exception
    }    
    @finally {        
      //@finally中的代碼是一定會(huì)執(zhí)行的
      //你可以在這里進(jìn)行一些相應(yīng)的操作
    }
    

崩潰日志

關(guān)于修復(fù)崩潰的Bug,如果你憑借自己的經(jīng)驗(yàn)师郑,有時(shí)候可能會(huì)遇到問題卡住环葵,我想最快的方式就是通過分析崩潰日志來解決崩潰。

什么是崩潰日志宝冕,從哪里能得它
iOS設(shè)備上的應(yīng)用閃退時(shí)张遭,操作系統(tǒng)會(huì)生成一個(gè)崩潰報(bào)告,也叫崩潰日志地梨,保存在設(shè)備上菊卷。

崩潰日志上有很多有用的信息,包括應(yīng)用是什么情況下閃退的宝剖。通常洁闰,上面有每個(gè)正在執(zhí)行線程的完整堆棧跟蹤信息,所以你能從中了解到閃退發(fā)生時(shí)各線程都在做什么诈闺,并分辨出閃退發(fā)生在哪個(gè)線程上渴庆。

有幾種方法可以從設(shè)備上獲取崩潰日志铃芦。

  • xcode中查看崩潰信息
    xcode->Window->Organizer->Crashes


  • 通過Xcode查看設(shè)備崩潰信息
    除了上面的系統(tǒng)分析工具來進(jìn)行分析雅镊,如果是我們自己直接使用手機(jī)連接崩潰或者崩潰之后連接手機(jī),選擇window-> devices -> 選擇自己的手機(jī) -> view device logs 就可以查看我們的崩潰信息了刃滓。


  • 使用第三方軟件:itools
    如果你平時(shí)不用iTunes仁烹,而是使用itools這類第三方的軟件對(duì)iPhone設(shè)備進(jìn)行管理,也是沒問題的咧虎。


    打開itools卓缰,在你的設(shè)備下,找到“高級(jí)功能”砰诵,點(diǎn)擊“崩潰日志”征唬,然后將需要的日志導(dǎo)出到電腦里面就可以了!

  • 應(yīng)用提交到App Store后茁彭,你也能從 iTunes Connect 獲取到用戶的崩潰日志. 登錄到 iTunes Connect 上, 選擇 Manage Your Applications, 點(diǎn)擊相應(yīng)的應(yīng)用, 點(diǎn)擊應(yīng)用圖標(biāo)下面的 View Details 按鈕, 然后點(diǎn)擊右欄Links部分的 Crash Reports 总寒。

什么時(shí)候不會(huì)產(chǎn)生崩潰日志
以下情況不會(huì)有崩潰信息產(chǎn)生:

  • 內(nèi)存訪問錯(cuò)誤(不是野指針錯(cuò)誤)
  • 低內(nèi)存,當(dāng)程序內(nèi)存使用過多會(huì)造成系統(tǒng)低內(nèi)存的問題理肺,系統(tǒng)會(huì)將程序內(nèi)存回收
  • 因?yàn)槟撤N原因觸發(fā)看門狗機(jī)制

一般Xcode不輸出Crash日志有一下幾個(gè)可能:

  1. NSSetUncaughtExceptionHandler() 可能被重寫了,(比如你引用了一些第三方庫, 它的SDK里面可能包含了把Crash的日志上傳到服務(wù)器, 這樣這個(gè)日志可能被重寫了, 就不打印本地的崩潰信息了) 盡量把它放在didFinishLaunchingWithOptions 最后面的一行代碼塊里.

  2. 還一種崩潰的情況是 EXC_BAD_ACCESS 摄闸,EXC_BAD_ACCESS異常的本意是指訪問不到內(nèi)存中這個(gè)地址的值善镰,可能是由于些變量已經(jīng)被回收了,亦可能是由于使用棧內(nèi)存的基本類型的數(shù)據(jù)賦值給了id類型的變量年枕。當(dāng)遇到這種錯(cuò)誤, 控制一般不會(huì)給你很多關(guān)于崩潰的信息, 這種崩潰你開啟僵尸對(duì)象模式即可, 不過記住你在正式發(fā)布的時(shí)候記得把這個(gè)勾取消, 不然會(huì)造成內(nèi)存泄漏炫欺。*

解析崩潰日志

.dSYM 文件

.dSYM 文件稱為符號(hào)表,是指在Xcode項(xiàng)目編譯后熏兄,在編譯生成的二進(jìn)制文件.app的同級(jí)目錄下生成的同名的.dSYM文件品洛。

.dSYM文件其實(shí)是一個(gè)目錄,在子目錄中包含了一個(gè)16進(jìn)制的保存函數(shù)地址映射信息的中轉(zhuǎn)文件霍弹,所有Debug的symbols都在這個(gè)文件中(包括文件名毫别、函數(shù)名、行號(hào)等)典格,所以也稱之為調(diào)試符號(hào)信息文件岛宦。符號(hào)表就是用來符號(hào)化 crash log(崩潰日志)。crash log中有一些方法16進(jìn)制的內(nèi)存地址等耍缴,通過符號(hào)表就能找到對(duì)應(yīng)的能夠直觀看到的方法名之類砾肺。

符號(hào)集是我們對(duì)ipa文件進(jìn)行打包之后,和.app文件同級(jí)的后綴名為.dSYM的文件防嗡,這個(gè)文件必須使用Xcode進(jìn)行打包才有变汪。每一個(gè).dSYM文件都有一個(gè)UUID,和.app文件中的UUID對(duì)應(yīng)蚁趁,代表著是一個(gè)應(yīng)用裙盾。而.dSYM文件中每一條崩潰信息也有一個(gè)單獨(dú)的UUID,用來和程序的UUID進(jìn)行校對(duì)他嫡。這些UUID一致時(shí)才可以解析出當(dāng)前APP的崩潰信息.

我們在Archive的時(shí)候會(huì)生成.xcarchive文件番官,然后顯示包內(nèi)容就能夠在里面找到.dsYM文件和.app文件。

所以 為了更好的分析崩潰原因钢属,在每次上架APP的時(shí)候徘熔,應(yīng)該保留對(duì)應(yīng)的app文件和dsym文件。

當(dāng)獲得一份crash日志時(shí)淆党,我們需要將初始展示的十六進(jìn)制地址等原始信息映射為源代碼級(jí)別的方法名稱和代碼行數(shù)酷师,使其對(duì)開發(fā)人員可讀。這個(gè)過程稱為符號(hào)化解析染乌。要成功地符號(hào)化解析一份crash日志山孔,我們需要有對(duì)應(yīng)的應(yīng)用程序二進(jìn)制文件以及符號(hào)(.dSYM)文件。

當(dāng)程序崩潰的時(shí)候荷憋,我們可以獲得到崩潰的錯(cuò)誤堆棧台颠,但是這個(gè)錯(cuò)誤堆棧都是0x開頭的16進(jìn)制地址,需要我們使用Xcode自帶的symbolicatecrash工具來將.Crash和.dSYM文件進(jìn)行符號(hào)化台谊,就可以得到詳細(xì)崩潰的信息蓉媳。

Symbolicatecrash
Symbolicatecrash是Xcode自帶的一個(gè)分析工具譬挚,可以通過機(jī)器上的崩潰日志和應(yīng)用的.dSYM文件定位發(fā)生崩潰的位置,把crash日志中的地址替換成代碼相應(yīng)位置酪呻。

使用效果:

分析前:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 CoreFoundation 0x3723b870 0x37180000 + 768112
1 CoreFoundation 0x37196648 0x37180000 + 91720
2 CoreFoundation 0x37181e90 0x37180000 + 7824
3 CoreFoundation 0x3718bb74 0x37180000 + 47988
4 CoreFoundation 0x3718ba8e 0x37180000 + 47758
5 UIKit 0x30f0f866 0x30f0a000 + 22630

分析后:
0 CoreFoundation 0x3723b870 ___forwarding___ + 136
1 CoreFoundation 0x37196648 _CF_forwarding_prep_0 + 40
2 CoreFoundation 0x37181e90 CFRetain + 76
3 CoreFoundation 0x3718bb74 +[__NSArrayI __new::] + 48
4 CoreFoundation 0x3718ba8e -[__NSPlaceholderArray initWithObjects:count:] + 294
5 UIKit 0x30f0f866 -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:] + 70

在這個(gè)路徑下你可以得到系統(tǒng)自帶的Symbolicatecrash减宣,把它拷貝到指定的文件下

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources

獲取.dSYM文件

選中archive的版本右擊,選擇Show in Finder就可以選中archived 文件然后顯示包內(nèi)容玩荠,就可以找到dSYM文件了漆腌。


解析步驟

  • 我在解析崩潰信息的時(shí)候,首先在桌面上建立一個(gè)Crash文件夾阶冈,然后將.Crash闷尿、app、.dSYM女坑、symbolicatecrash放在這個(gè)文件夾中填具。

Paste_Image.png

注意:這里的 .crash 必須是真機(jī)安裝的打包的那個(gè) sometwo 產(chǎn)生的崩潰日志才行,運(yùn)行其他的版本產(chǎn)生的崩潰日志匆骗,以下的解析會(huì)失敗劳景。

如何把這個(gè)打包的應(yīng)用安裝到測試機(jī)上呢?注意這里的應(yīng)用不是 ipa文件碉就,而且這個(gè)手機(jī)也可以沒被加入到當(dāng)前的開發(fā)者賬號(hào)中盟广。

手機(jī)連上 itunes,在itunes中打開 手機(jī)的應(yīng)用瓮钥, 文件->添加到資料庫 把桌面是上的那個(gè)應(yīng)用添加進(jìn)入筋量,再同步更新到測試機(jī)器中即可。

Paste_Image.png

如果你一直解析失敗碉熄,那么可能你的 .Crash桨武、app、.dSYM具被、的UUID不一致玻募,通過終端工具可以查看 app只损、 .dSYM文件的UUID:

cd到文件夾
dwarfdump --uuid Sometwo.app/Sometwo
dwarfdump --uuid Sometwo.app.dSYM
三者一致才能還原符號(hào)表一姿。
Paste_Image.png

Paste_Image.png

由上圖可以看出三折的UUID是不一致的,所以會(huì)一直解析失敗跃惫,無法符號(hào)化 .Crash文件叮叹。

在終端中輸入以下命令, iOS002 換成你自己的用戶名稱

  • cd /Users/iOS002/Desktop/Cash/
  • export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"
  • ./symbolicatecrash /Users/iOS002/Desktop/Cash/SomeTwo.crash /Users/iOS002/Desktop/Cash/SomeTwo.app.dSYM > Control_symbol.crash

一切正常的話這樣就完成了一個(gè)崩潰日志的解析工作爆存。解析完成后會(huì)生成一個(gè)新的.Crash文件蛉顽,這個(gè)文件中就是崩潰詳細(xì)信息。圖中紅色標(biāo)注的部分就是我們代碼崩潰的部分先较。

收集崩潰日志

獲取崩潰信息方式
在iOS中獲取崩潰信息的方式有很多携冤,比較常見的是使用友盟悼粮、云測、百度曾棕、Crashlytics等第三方分析工具扣猫,或者自己收集崩潰信息并上傳公司服務(wù)器。下面列舉一些我們常用的崩潰分析方式:

  • 自己實(shí)現(xiàn)應(yīng)用內(nèi)崩潰收集翘地,并上傳服務(wù)器申尤。
  • 使用友盟、云測衙耕、百度昧穿、Crashlytics等第三方崩潰統(tǒng)計(jì)工具。

自己收集崩潰信息

蘋果給我們提供了異常處理的類橙喘,NSException類时鸵。這個(gè)類可以創(chuàng)建一個(gè)異常對(duì)象,也可以通過這個(gè)類獲取一個(gè)異常對(duì)象厅瞎。這個(gè)類中我們最常用的還是一個(gè)獲取崩潰信息的C函數(shù)寥枝,我們可以通過這個(gè)函數(shù)在程序發(fā)生異常的時(shí)候收集這個(gè)異常。然后把收集到的崩潰信息發(fā)送到自己的服務(wù)器磁奖。

我們也可以通過下面方法獲取崩潰統(tǒng)計(jì)的函數(shù)指針:

 NSUncaughtExceptionHandler *handler = NSGetUncaughtExceptionHandler();
 NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);
//  收集崩潰信息的調(diào)用方法
void UncaughtExceptionHandler(NSException *exception) {
    NSArray *arr = [exceptioncallStackSymbols];//得到當(dāng)前調(diào)用棧信息
    NSString *reason = [exceptionreason];//非常重要囊拜,就是崩潰的原因
    NSString *name = [exceptionname];//異常類型
    NSLog(@"exception type : %@ \n crash reason : %@ \n call stack info : %@", name, reason, arr);
}

獲取到了崩潰的發(fā)送給開發(fā)者有以下兩種方式:

  1. 將崩潰信息持久化在本地,下次程序啟動(dòng)時(shí)比搭,將崩潰信息作為日志發(fā)送給開發(fā)者冠跷。

  2. 通過郵件發(fā)送給開發(fā)者。不過此種方式需要得到用戶的許可身诺,因?yàn)閕OS不能后臺(tái)發(fā)送短信或者郵件蜜托,會(huì)彈出發(fā)送郵件的界面,只有用戶點(diǎn)擊了發(fā)送才可發(fā)送霉赡。不過橄务,此種方式最符合蘋果的以用戶至上的原則。

    發(fā)送郵件代碼:
    NSString *crashLogInfo = [NSString stringWithFormat:@"exception type : %@ \n crash reason : %@ \n callstack info : %@", name, reason, arr];
    NSString*urlStr = [NSString stringWithFormat:@"mailto://tianranwuwai@yeah.net?subject=bug報(bào)告&body=感謝您的配合! 錯(cuò)誤詳情:%@",crashLogInfo];
    NSURL *url =[NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    [[UIApplication sharedApplication] openURL:url];
    

我們是否也可以在程序崩潰時(shí)穴亏,將崩潰信息寫入本地蜂挪,APP再次啟動(dòng)時(shí),將崩潰信息上傳到我們的服務(wù)器嗓化。這里就要用到apple的一個(gè)函數(shù):NSSetUncaughtExceptionHandler棠涮。上代碼:

   application didFinishLaunchingWithOptions中調(diào)用
   [self catchCrashLogs];

    - (void)catchCrashLogs{
        NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
    }
  
   void UncaughtExceptionHandler(NSException *exception){
      if (exception ==nil)return;
        NSArray *array = [exception callStackSymbols];
        NSString *reason = [exception reason];
        NSString *name  = [exception name];
        NSDictionary *dict = @{@"appException":@{@"exceptioncallStachSymbols":array,@"exceptionreason":reason,@"exceptionname":name}};
    if([SDFileToolClass writeCrashFileOnDocumentsException:dict]){
        NSLog(@"Crash logs write ok!");
    }
   }
    //寫入緩存中: 以下提供三個(gè)API,分別是:寫入刺覆,獲取严肪,清空
    NSString * const SDCrashFileDirectory = @"SDMapHomeCrashFileDirectory"; //你的項(xiàng)目中自定義文件夾名
    + (NSString *)sd_getCachesPath{
        return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    }
    + (BOOL)writeCrashFileOnDocumentsException:(NSDictionary *)exception{
    NSString *time = [[NSDate date] formattedDateWithFormat:@"yyyyMMddHHmmss" locale:[NSLocale currentLocale]];
    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString *crashname = [NSString stringWithFormat:@"%@_%@Crashlog.plist",time,infoDictionary[@"CFBundleName"]];
    NSString *crashPath = [[self sd_getCachesPath] stringByAppendingPathComponent:SDCrashFileDirectory];
    NSFileManager *manager = [NSFileManager defaultManager];
    //設(shè)備信息
    NSMutableDictionary *deviceInfos = [NSMutableDictionary dictionary];
    [deviceInfos setObject:[infoDictionary objectForKey:@"DTPlatformVersion"] forKey:@"DTPlatformVersion"];
    [deviceInfos setObject:[infoDictionary objectForKey:@"CFBundleShortVersionString"] forKey:@"CFBundleShortVersionString"];
    [deviceInfos setObject:[infoDictionary objectForKey:@"UIRequiredDeviceCapabilities"] forKey:@"UIRequiredDeviceCapabilities"];

    BOOL isSuccess = [manager createDirectoryAtPath:crashPath withIntermediateDirectories:YES attributes:nil error:nil];
    if (isSuccess) {
        NSLog(@"文件夾創(chuàng)建成功");
        NSString *filepath = [crashPath stringByAppendingPathComponent:crashname];
        NSMutableDictionary *logs = [NSMutableDictionary dictionaryWithContentsOfFile:filepath];
        if (!logs) {
            logs = [[NSMutableDictionary alloc] init];
        }
        //日志信息
        NSDictionary *infos = @{@"Exception":exception,@"DeviceInfo":deviceInfos};
        [logs setObject:infos forKey:[NSString stringWithFormat:@"%@_crashLogs",infoDictionary[@"CFBundleName"]]];
        BOOL writeOK = [logs writeToFile:filepath atomically:YES];
        NSLog(@"write result = %d,filePath = %@",writeOK,filepath);
        return writeOK;
    }else{
        return NO;
      }
    }
    + (nullable NSArray *)sd_getCrashLogs{
     NSString *crashPath = [[self sd_getCachesPath] stringByAppendingPathComponent:SDCrashFileDirectory];
     NSFileManager *manager = [NSFileManager defaultManager];
     NSArray *array = [manager contentsOfDirectoryAtPath:crashPath error:nil];
     NSMutableArray *result = [NSMutableArray array];
    if (array.count == 0) return nil;
    for (NSString *name in array) {
        NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:[crashPath stringByAppendingPathComponent:name]];
        [result addObject:dict];
    }
    return result;
    }

    + (BOOL)sd_clearCrashLogs{
     NSString *crashPath = [[self sd_getCachesPath] stringByAppendingPathComponent:SDCrashFileDirectory];
    NSFileManager *manager = [NSFileManager defaultManager];
    if (![manager fileExistsAtPath:crashPath]) return YES; //如果不存在,則默認(rèn)為刪除成功
    NSArray *contents = [manager contentsOfDirectoryAtPath:crashPath error:NULL];
    if (contents.count == 0) return YES;
    NSEnumerator *enums = [contents objectEnumerator];
    NSString *filename;
    BOOL success = YES;
    while (filename = [enums nextObject]) {
        if(![manager removeItemAtPath:[crashPath stringByAppendingPathComponent:filename] error:NULL]){
            success = NO;
            break;
        }
    }
    return success;
    }

使用工具Crashlytics統(tǒng)計(jì)Crash

市場上有多種移動(dòng)應(yīng)用Crash收集工具, 如友盟,MTJ等驳糯。在iOS中篇梭, 收集Crash主要通過兩種方式, 一種是信號(hào)量機(jī)制酝枢,因?yàn)閏rash通常會(huì)發(fā)出信號(hào)量很洋,標(biāo)明某某應(yīng)用崩潰了, 另一種方式是每一個(gè)應(yīng)用都有一個(gè)crash handle, 即崩潰鉤子隧枫, 每當(dāng)程序崩潰時(shí)喉磁, 都會(huì)執(zhí)行這個(gè)回調(diào)。信號(hào)量比起崩潰句柄的區(qū)別有點(diǎn)像ios開發(fā)中的通知和delegate官脓。 信號(hào)量拋出后协怒,可以被多個(gè)捕獲crash的工具獲取到,然后取當(dāng)前的堆棧信息卑笨, 再利用該堆棧信息與原app的dsym文件進(jìn)行比對(duì)孕暇, 就可以找到崩潰的代碼行。
理論上講赤兴, 這個(gè)信號(hào)量機(jī)制優(yōu)秀于crash句柄妖滔, 因?yàn)檫@樣的話,可以有多個(gè)收集工具并行收集桶良, 前提是座舍,每個(gè)收集工具收集后,繼續(xù)拋出這個(gè)異常陨帆,而不是截?cái)噙@個(gè)異常曲秉,當(dāng)截?cái)嗪蠛罄m(xù)的其它工具就收集不到這個(gè)異常了, 會(huì)導(dǎo)致其它工具收集不全的問題疲牵。 而友盟正是這樣做的.
利用crash 句柄這種方式使得crash信息只能被一個(gè)收集工具所收集到承二,因?yàn)榫浔挥幸粋€(gè)。如果一個(gè)應(yīng)用中有多個(gè)收集工具都設(shè)置了這個(gè)句柄纲爸, 這里就得看誰最后設(shè)置這個(gè)句柄亥鸠, 誰就有效。

上面是收集crash的方式說明识啦, 現(xiàn)在說說Crashlytics這個(gè)工具负蚊。 原理和上面的一樣。 不一樣的是袁滥, 這個(gè)工具被twitter收購盖桥, 既然有這么一根大樹灾螃, 那就保證了這個(gè)工具的穩(wěn)定性题翻。 所以建議使用, 目前是免費(fèi)的。
使用步驟基本上可以分為如下:

  • 注冊嵌赠,
  • 收到邀請(qǐng)信塑荒, 然后一步步按其說明完成注冊。
  • 根據(jù)其提示姜挺,下載一個(gè)mac app配合進(jìn)行使用齿税。
  • 當(dāng)有崩潰發(fā)生時(shí),會(huì)給注冊的郵件發(fā)送崩潰統(tǒng)計(jì)炊豪,方便查看凌箕。

在crash信息收集時(shí), 如果正在進(jìn)行debug調(diào)試词渤,是收集不到信息的牵舱。

使用Crashlytics的好處:

  • Crashlytics不會(huì)漏掉任何應(yīng)用崩潰信息(就這兩個(gè)字讓我決定使用crashlytics)
  • Crashlytics可以象Bug管理工具那樣,管理這些崩潰日志缺虐, 可以根據(jù)頻率及影響用戶量來自動(dòng)設(shè)置優(yōu)先級(jí)
  • 可以每天和每周將崩潰信息匯總發(fā)送到郵箱中芜壁。

具體使用,可以參照這篇文章Crashlytics

小結(jié)

有關(guān)應(yīng)用Crash的處理工作任重而道遠(yuǎn)高氮,后續(xù)會(huì)持續(xù)更新慧妄,先寫這些吧。


本文參考文章:
關(guān)于崩潰日志解讀很詳細(xì)很棒的的一篇文章
iOS被開發(fā)者遺忘在角落的NSException-其實(shí)它很強(qiáng)大
iOS崩潰調(diào)試(收集不同用戶的崩潰信息)

Paste_Image.png

Paste_Image.png

模擬器打印不出來 malloc stock的信息剪芍,需要真機(jī)塞淹。

1.unrecognized seletor。錯(cuò)誤:這種情況很簡單罪裹,給一個(gè)對(duì)象發(fā)送了一條它不認(rèn)識(shí)的消息窖铡。比如說你的.h中聲明了某一個(gè)方法,但是.m中卻沒有實(shí)現(xiàn)坊谁,而且你沒有對(duì)異常消息處理(消息轉(zhuǎn)發(fā))就會(huì)造成這種現(xiàn)象费彼。解決辦法:首先排查自己的某一些方法是否實(shí)現(xiàn),其次看一下哪些對(duì)象接收了它不該接收的消息口芍。

2.index 1 beyond NSArraMu [0,0]數(shù)組越界:數(shù)組越界這個(gè)不多說箍铲。

3.NSNul length 這個(gè)異常以可以歸類為第一種,也是給某一個(gè)對(duì)象發(fā)送了不識(shí)別的消息鬓椭。常見原因有:給UILabel對(duì)象設(shè)置了text颠猴,此時(shí)的text內(nèi)容為空字符串null,然后你在取text的length的時(shí)候就會(huì)拋出異常小染。

4.EXC_BAD_ACCESS異常:這種大多數(shù)是對(duì)象提前釋放翘瓮,訪問了野指針的錯(cuò)誤。解決辦法:排查所有聲明為weak對(duì)象的使用裤翩,是否在沒有持有的情況下再次訪問了該對(duì)象(該對(duì)象已經(jīng)被釋放)资盅,第二在MRC情況下,排查一下所以已經(jīng)release的對(duì)象(聲明一點(diǎn),MRC中全局變量最好在dealloc方法中進(jìn)行釋放)呵扛,第三排查一下所有block每庆,是否block被正常賦值等。

5.崩潰在main函數(shù)今穿。這種情況最苦逼也是最難找到bug所在缤灵,這種情況下,用@try @catch將main函數(shù)包裹起來蓝晒,這樣會(huì)拋出異常堆棧信息等腮出,或者通過添加全局breakPoint來追蹤bug。(扯淡)

@try @catch 是最后的大招

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末芝薇,一起剝皮案震驚了整個(gè)濱河市利诺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌剩燥,老刑警劉巖慢逾,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異灭红,居然都是意外死亡侣滩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門变擒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來君珠,“玉大人,你說我怎么就攤上這事娇斑〔咛恚” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵毫缆,是天一觀的道長唯竹。 經(jīng)常有香客問我,道長苦丁,這世上最難降的妖魔是什么浸颓? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮旺拉,結(jié)果婚禮上产上,老公的妹妹穿的比我還像新娘。我一直安慰自己蛾狗,他們只是感情好晋涣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沉桌,像睡著了一般谢鹊。 火紅的嫁衣襯著肌膚如雪算吩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天撇贺,我揣著相機(jī)與錄音赌莺,去河邊找鬼冰抢。 笑死松嘶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挎扰。 我是一名探鬼主播翠订,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼遵倦!你這毒婦竟也來了尽超?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤梧躺,失蹤者是張志新(化名)和其女友劉穎似谁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掠哥,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡巩踏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了续搀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片塞琼。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖禁舷,靈堂內(nèi)的尸體忽然破棺而出彪杉,到底是詐尸還是另有隱情,我是刑警寧澤牵咙,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布派近,位于F島的核電站,受9級(jí)特大地震影響洁桌,放射性物質(zhì)發(fā)生泄漏构哺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一战坤、第九天 我趴在偏房一處隱蔽的房頂上張望曙强。 院中可真熱鬧,春花似錦途茫、人聲如沸碟嘴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娜扇。三九已至错沃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間雀瓢,已是汗流浹背枢析。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刃麸,地道東北人醒叁。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像泊业,于是被迫代替她去往敵國和親把沼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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