IOS开发中分析carsh log文件

来源:互联网 发布:太原java薪资待遇如何 编辑:程序博客网 时间:2024/05/29 19:36

iOS crash log 解析

一 、crash log 文件解析前需要做的工作:

说明:crash log 文件一般是十六进制文件,所以需要我们去解析成我们能够看懂的 crash log 文件,解析之前一般我们需要获取以下四个文件:

1. 获取 .crash文件,既然都要解析 crash log 了,说明你已经拿到 crash log 文件了,所以在此不讲解通过何种渠道获取crash log文件

2. 获取符号文件:.dsymb文件( 获取途径:首先打开 Xcode,接着点击 Window 中的 Organizer ,选择 Archives 中的你自己需要的应用程序工程,此时双击选择 Show in Finder ,再次双击你需要的应用程序工程 .xcarchive 文件,选择显示包内容,然后选择 dSYMs 文件夹中的 .dsymb 文件,这就是你需要的.dsymb 文件。

3. 获取应用程序文件(把你打包的appName.ipa文件,后缀改为zip,然后解压,解压后的Payload目录下的appName.app文件就是你需要的应用程序文件。说明:appName就是你的应用程序的名称)

4. 获取 symbolicatecrash 文件(路径:/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources 

然后将获取到的以上四个文件放到同一个文件目录下。

特别说明:需要找出在上传应用时所发送的 .app文件和.DSYM文件,切记每次发送新版本都要保留这两个文件,不然没有办法解析crash log。

解析前的crash log 文件打开查看都是十六进制的地址,如下:

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread:  0


Last Exception Backtrace:
(0x2dda0fce 0x38520cca 0x2dda0f10 0x2e70b310 0x2e70ae52 0x2e706b90 0x305bbcee 0x308542c6 0x305babdc 0x306826a0 0x305f4d72 0x305f3382 0x306741ca 0x30673ae6 0x3066b990 0x3066ae18 0x3066ab88 0x3066ab20 0x305bcd74 0x3023a626 0x30235e36 0x30235cc8 0x302356da 0x302354ea 0x305c03fc 0x2dd6c256 0x2dd6b726 0x2dd69f1a 0x2dcd4f4a 0x2dcd4d2e 0x32bd965e 0x30620168 0x2e5df6 0x38a2dab2)


Thread 0 Crashed:
0   libsystem_kernel.dylib         0x38ae31f0 0x38ad0000 + 78320
1   libsystem_pthread.dylib       0x38b4d792 0x38b4a000 + 14226
2   libsystem_c.dylib             0x38a93fd8 0x38a4b000 + 298968
3   libc++abi.dylib               0x37dc2cd2 0x37dc2000 + 3282
4   libc++abi.dylib               0x37ddb6e0 0x37dc2000 + 104160
5   libobjc.A.dylib               0x38520f62 0x3851d000 + 16226
6   libc++abi.dylib               0x37dd91c4 0x37dc2000 + 94660
7   libc++abi.dylib               0x37dd8d28 0x37dc2000 + 93480
8   libobjc.A.dylib               0x38520e12 0x3851d000 + 15890
9   CoreFoundation                 0x2dcd4fc0 0x2dccd000 + 32704
10  CoreFoundation                 0x2dcd4d2e 0x2dccd000 + 32046
11  GraphicsServices               0x32bd965e 0x32bd0000 + 38494
12  UIKit                         0x30620168 0x305b2000 + 450920
13  USchoolCircle                 0x002e5df6 0xcb000 + 2207222
14  libdyld.dylib                 0x38a2dab4 0x38a2c000 + 6836


Thread 1:
0   libsystem_kernel.dylib         0x38ad0808 0x38ad0000 + 2056
1   libdispatch.dylib             0x38a1cde8 0x38a07000 + 89576
2   libdispatch.dylib             0x38a0bf6e 0x38a07000 + 20334

Thread 0 crashed with ARM Thread State (32-bit):
    r0: 0x00000000    r1: 0x00000000      r2: 0x00000000      r3: 0x38a86aa9
    r4: 0x00000006    r5: 0x3a83f18c      r6: 0x00000000      r7: 0x27d38584
    r8: 0x1693b470    r9: 0x00000001     r10: 0x00000000     r11: 0x38cf2500
    ip: 0x00000148    sp: 0x27d38578      lr: 0x38b4d797      pc: 0x38ae31f0
  cpsr: 0x00000010


Binary Images:
0xcb000 - 0x3b6fff USchoolCircle armv7  <4318259741bd3970916734d1da9f9417> /var/mobile/Applications/82667236-7A46-4E36-AB61-8D0D3C7B0E2A/USchoolCircle.app/USchoolCircle
0x435000 - 0x668fff libswiftCore.dylib armv7  <9cb2727f51e13415bafc92fe12f7e036> /var/mobile/Applications/82667236-7A46-4E36-AB61-8D0D3C7B0E2A/USchoolCircle.app/Frameworks/libswiftCore.dylib

 I/TestinExternalLog(1): <<<<<<< StopTest ui Package com.uskytec.USchoolCircle >>>>>>>


二、crash log 文件解析:

第一种解析方式:使用 Symbolicatecrash 解析,步骤如下:

1. 在开始解析之前需要先进行一些关于UUID的校验;

(1)查看xx.app文件的uuid的方法,在命令行中输入:

    $ dwarfdump --uuid xxx.app/xxx (xxx工程名)

(2)查看xx.app.dSYM文件的uuid的方法,在命令行输入:

    $ dwarfdump --uuid xxx.app.dSYM (xxx工程名)

(3)查看.crashuuid,位于crash日志中的Binary Images:中的第一行。如:armv7s  <13760bde0d073f1eb4d596c3df753f4b>


只有三者的uuid相同才能解析.crash文件,


2. 输入命令进入到四个文件所在的文件目录下; 

3. 然后在终端的命令行输入:

$ ./symbolicatecrash xxx.crash xxx.app.dSYM > test.log

这样可以将.crash日志转换成test.logtest.log即可读的函数文件。


特别说明:输入上述命令可能会出现Error: "DEVELOPER_DIR" is not defined at ./symbolicatecrash line 53.这个错误。

如果出现上述错误,输入命令:export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer

然后继续执行./symbolicatecrash xxx.crash xxx.app.dSYM > test.log可以成功


解析后的 crash log 文件,如下:

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread:  0


Last Exception Backtrace:
0   CoreFoundation                 0x2dda0fce 0x2dccd000 + 868302
1   libobjc.A.dylib               0x38520cca 0x3851d000 + 15562
2   CoreFoundation                 0x2dda0f10 0x2dccd000 + 868112
3   Foundation                     0x2e70b310 0x2e6bb000 + 328464
4   Foundation                     0x2e70ae52 0x2e6bb000 + 327250
5   Foundation                     0x2e706b90 0x2e6bb000 + 310160
6   UIKit                         0x305bbcee 0x305b2000 + 40174
7   UIKit                         0x308542c6 0x305b2000 + 2761414
8   UIKit                         0x305babdc 0x305b2000 + 35804
9   UIKit                         0x306826a0 0x305b2000 + 853664
10  UIKit                         0x305f4d72 0x305b2000 + 273778
11  UIKit                         0x305f3382 0x305b2000 + 267138
12  UIKit                         0x306741ca 0x305b2000 + 795082
13  UIKit                         0x30673ae6 0x305b2000 + 793318
14  UIKit                         0x3066b990 0x305b2000 + 760208
15  UIKit                         0x3066ae18 0x305b2000 + 757272
16  UIKit                         0x3066ab88 0x305b2000 + 756616
17  UIKit                         0x3066ab20 0x305b2000 + 756512
18  UIKit                         0x305bcd74 0x305b2000 + 44404
19  QuartzCore                     0x3023a626 0x3022e000 + 50726
20  QuartzCore                     0x30235e36 0x3022e000 + 32310
21  QuartzCore                     0x30235cc8 0x3022e000 + 31944
22  QuartzCore                     0x302356da 0x3022e000 + 30426
23  QuartzCore                     0x302354ea 0x3022e000 + 29930
24  UIKit                         0x305c03fc 0x305b2000 + 58364
25  CoreFoundation                 0x2dd6c256 0x2dccd000 + 651862
26  CoreFoundation                 0x2dd6b726 0x2dccd000 + 648998
27  CoreFoundation                 0x2dd69f1a 0x2dccd000 + 642842
28  CoreFoundation                 0x2dcd4f4a 0x2dccd000 + 32586
29  CoreFoundation                 0x2dcd4d2e 0x2dccd000 + 32046
30  GraphicsServices               0x32bd965e 0x32bd0000 + 38494
31  UIKit                         0x30620168 0x305b2000 + 450920
32  USchoolCircle                 0x002e5df6 main (main.m:14) 
33  libdyld.dylib                 0x38a2dab2 0x38a2c000 + 6834




Thread 0 Crashed:
0   libsystem_kernel.dylib         0x38ae31f0 0x38ad0000 + 78320
1   libsystem_pthread.dylib       0x38b4d792 0x38b4a000 + 14226
2   libsystem_c.dylib             0x38a93fd8 0x38a4b000 + 298968
3   libc++abi.dylib               0x37dc2cd2 0x37dc2000 + 3282
4   libc++abi.dylib               0x37ddb6e0 0x37dc2000 + 104160
5   libobjc.A.dylib               0x38520f62 0x3851d000 + 16226
6   libc++abi.dylib               0x37dd91c4 0x37dc2000 + 94660
7   libc++abi.dylib               0x37dd8d28 0x37dc2000 + 93480
8   libobjc.A.dylib               0x38520e12 0x3851d000 + 15890
9   CoreFoundation                 0x2dcd4fc0 0x2dccd000 + 32704
10  CoreFoundation                 0x2dcd4d2e 0x2dccd000 + 32046
11  GraphicsServices               0x32bd965e 0x32bd0000 + 38494
12  UIKit                         0x30620168 0x305b2000 + 450920
13  USchoolCircle                 0x002e5df6 main (main.m:14) 
14  libdyld.dylib                 0x38a2dab4 0x38a2c000 + 6836


Thread 1:
0   libsystem_kernel.dylib         0x38ad0808 0x38ad0000 + 2056
1   libdispatch.dylib             0x38a1cde8 0x38a07000 + 89576
2   libdispatch.dylib             0x38a0bf6e 0x38a07000 + 20334


Thread 0 crashed with ARM Thread State (32-bit):
    r0: 0x00000000    r1: 0x00000000      r2: 0x00000000      r3: 0x38a86aa9
    r4: 0x00000006    r5: 0x3a83f18c      r6: 0x00000000      r7: 0x27d38584
    r8: 0x1693b470    r9: 0x00000001     r10: 0x00000000     r11: 0x38cf2500
    ip: 0x00000148    sp: 0x27d38578      lr: 0x38b4d797      pc: 0x38ae31f0
  cpsr: 0x00000010


Binary Images:
0xcb000 - 0x3b6fff USchoolCircle armv7  <4318259741bd3970916734d1da9f9417> /var/mobile/Applications/82667236-7A46-4E36-AB61-8D0D3C7B0E2A/USchoolCircle.app/USchoolCircle
0x435000 - 0x668fff libswiftCore.dylib armv7  <9cb2727f51e13415bafc92fe12f7e036> /var/mobile/Applications/82667236-7A46-4E36-AB61-8D0D3C7B0E2A/USchoolCircle.app/Frameworks/libswiftCore.dylib

 I/TestinExternalLog(1): <<<<<<< StopTest ui Package com.uskytec.USchoolCircle >>>>>>>


有时候解析出来的文件效果我们不满意,那么下面我们根据第二种方式解析。


第二种解析方式(根据地址解析内容):

此外,还可以在上面三个uuid对应的情况下解析某一个地址的内容

$ xcrun atos -o xxx.app/xxx -arch armv7 0x002e5df6 0xcb000(多个16进制地址,使用空格分开)

解析出的结果如下:

-[SecondShotViewController playVideo] (in USchoolCircle) (SecondShotViewController.m:473)

=============================================================================================================

以上内容转载至:http://blog.csdn.net/xiao_long_li/article/details/50390432

总结:
   为什么我们需要去分析crash log文件?
要理解这一点很重要,平时我们开发是在xcode下,当程序在runing中奔溃的时候,我们能够立刻从控制台中查看到程序crash的堆栈信息,因此也能够很容易定位到出错的代码位置,这是因为我们编译运行的版本是debug版;但是,如果我们要发布我们的产品,就需要用release版本,这个时候如果程序crash掉,我们能够获得到的是上面的crash log文件(由16进制数组成),所以我们需要这么一道程序去分析定位出错的代码位置。要分析这个crash log文件,上面已经介绍的很详细了,我们需要的是出错的*.app文件,*.app.dSYM这个符号表文件,以及crash log 文件。但是正如我们所见,分析出来的效果依旧没什么卵用,通过在网上找答案,原因可能是因为本地没有IOS系统的符号表文件导致的,详细网址:使用symbolicatecrash解析了一个crash log,这样我们便可以解析出具体出问题的位置。
最后:
我们怎么得到crash文件呢,请查看这篇文章iOS开发之Crash日志获取与分析,这篇文章讲解了如何利用工具来获取crash log,但是,我们如何能够再程序中捕获这个异常呢?比如说,我们的线上程序,将异常保存到本地以便上传到服务器供程序员来解决问题?当然可以,以下为转载内容:
=================================================================地址:ios Crash闪退日志获取和上传至服务器(NSSetUncaughtExceptionHandler)

最近客户有个要求:人家谁谁有crash日志捕获和上传,我们是不是也要做一个...  人家谁谁.....还有什么什么功能........

  正好最近也在研究这方面东东,所以整理一下分享给大家:如何用程序获取Crash日志 并 可以上传Crash日志。


   首先我们整理经常会闪退的异常哪些:数组越界、空引用、引用未定义方法、内存空间不足等等。

   友盟分享后台是可以看到crash的日志,如下图:

   

        开始研究的时候,我有两个疑问:

        1.如何获取crash闪退日志(工具和程序两种方法);

        2.解析crash;

       

        说明:这里说的crash日志不是在联调的情况下(是生产环境,通俗的说就是发布了的产品)。


        如何获取crash闪退日志 -- 工具查看

        先看第一个问题如何查看,我搜索的方法有以下几个:

        第一个方法:XCode  的菜单Window->Organizer    选择Devices  ->  选中的手机 -> 点击手机名称左边的箭头 会等到如下图

        

       在右边竖蓝色矩形框中 Type里面出现两种类型:Unknown和Crash 这两种类型分别是 内存不够回收内存kill应用程序导致Crash和程序异常Crash的日志。


       上图是我在刚打开日志(立马、马上)截的图,否则过了5秒中,会变成这样(自动解析):

       

      注意对比一下红色框框内容,这个日志也基本上上告诉你crash的原因了。

      

       第二种方法 打开手机 - > 设置 -> 通用 - > 关于本机 - > 诊断与用量 - > 诊断与用量数据  这里面就是所有应用的Crash日志。

       第三种方法 通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash日志。方法很多这里不多列了。


      解析crash

      参见:http://stackoverflow.com/questions/1460892/symbolicating-iphone-app-crash-reports )

       

      用程序获取crash日志

      但是这里都是工具,没有用到程序获取,经过千方百计的查询(思路是:先找到存放crash的iphone系统路径:var/mobile/Library/Logs/CrashReporter)找到了crash存放的路径,唉,苦于无法读取(用程序读出来都是nil),当然如果是越狱手机就不一样是可以读取的。这个思路断掉了。


       换个思路:自己用程序捕获crash,保存到本地可以吗?这么一试,果然........

       第一步:新建一个继承自NSObject的类(Xcode新建一个空项目过程略),取名字CatchCrash,在h和m文件中写下:

       .h文件

       

[html] view plain copy
 print?
  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface CatchCrash : NSObject  
  4.   
  5. void uncaughtExceptionHandler(NSException *exception);  
  6.   
  7. @end  

       .m(m)文件

[html] view plain copy
 print?
  1. #import "CatchCrash.h"  
  2.   
  3. @implementation CatchCrash  
  4.   
  5. void uncaughtExceptionHandler(NSException *exception)  
  6. {  
  7.     // 异常的堆栈信息  
  8.     NSArray *stackArray = [exception callStackSymbols];  
  9.     // 出现异常的原因  
  10.     NSString *reason = [exception reason];  
  11.     // 异常名称  
  12.     NSString *name = [exception name];  
  13.     NSString *exceptionInfo = [NSString stringWithFormat:@"Exception reason:%@\nException name:%@\nException stack:%@",name, reason, stackArray];  
  14.     NSLog(@"%@", exceptionInfo);  
  15.       
  16.     NSMutableArray *tmpArr = [NSMutableArray arrayWithArray:stackArray];  
  17.     [tmpArr insertObject:reason atIndex:0];  
  18.       
  19.     //保存到本地  --  当然你可以在下次启动的时候,上传这个log  
  20.     [exceptionInfo writeToFile:[NSString stringWithFormat:@"%@/Documents/error.log",NSHomeDirectory()]  atomically:YES encoding:NSUTF8StringEncoding error:nil];  
  21. }  
  22.   
  23. @end  

       第二步:添加一个继承自UIViewcontroller的类,取名字为TestViewController。

       第三步:注册CatchCrash异常处理方法,在Appdelegate写下如下代码:

[html] view plain copy
 print?
  1. #import "AppDelegate.h"  
  2. #import "CatchCrash.h"  
  3. #import "TestViewController.h"  
  4.   
  5. @implementation AppDelegate  
  6.   
  7. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
  8. {  
  9.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  
  10.     // Override point for customization after application launch.  
  11.   
  12.     //注册消息处理函数的处理方法  
  13.     NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);  
  14.       
  15.     TestViewController *testVc = [[TestViewController alloc] init];  
  16.     self.window.rootViewController = testVc;  
  17.       
  18.     self.window.backgroundColor = [UIColor whiteColor];  
  19.     [self.window makeKeyAndVisible];  
  20.     return YES;  
  21. }  
  22.   
  23. - (void)applicationWillResignActive:(UIApplication *)application  
  24. {}  
  25.   
  26. - (void)applicationDidEnterBackground:(UIApplication *)application  
  27. {}  
  28.   
  29. - (void)applicationWillEnterForeground:(UIApplication *)application  
  30. {}  
  31.   
  32. - (void)applicationDidBecomeActive:(UIApplication *)application  
  33. {}  
  34.   
  35. - (void)applicationWillTerminate:(UIApplication *)application  
  36. {}  

       第四部:在TestViewController的Xib上面添加一个按钮并给其添加一个单击事件,TestViewController.m文件中有如下代码:
[html] view plain copy
 print?
  1. #import "TestViewController.h"  
  2.   
  3. @interface TestViewController ()  
  4.   
  5. @end  
  6.   
  7. @implementation TestViewController  
  8.   
  9. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
  10. {  
  11.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
  12.     if (self) {  
  13.         // Custom initialization  
  14.     }  
  15.     return self;  
  16. }  
  17.   
  18. - (void)viewDidLoad  
  19. {  
  20.     [super viewDidLoad];  
  21.     // Do any additional setup after loading the view from its nib.  
  22. }  
  23.   
  24. - (void)didReceiveMemoryWarning  
  25. {  
  26.     [super didReceiveMemoryWarning];  
  27.     // Dispose of any resources that can be recreated.  
  28. }  
  29.   
  30. #pragma mark - 单击事件  
  31. - (IBAction)crashTapped:(id)sender  
  32. {  
  33.     //常见异常1---不存在方法引用  
  34. //    [self performSelector:@selector(thisMthodDoesNotExist) withObject:nil];  
  35.       
  36.     //常见异常2---键值对引用nil  
  37. //    [[NSMutableDictionary dictionary] setObject:nil forKey:@"nil"];  
  38.       
  39.     //常见异常3---数组越界  
  40.     [[NSArray array] objectAtIndex:1];  
  41.       
  42.     //常见异常4---memory warning 级别3以上  
  43. //    [self performSelector:@selector(killMemory) withObject:nil];  
  44.       
  45.     //其他大家去想吧  
  46. }  
  47.   
  48. #pragma mark - custom method  
  49. - (void) killMemory  
  50. {  
  51.     for (int i = 0; i < 300; i ++)  
  52.     {  
  53.         UILabel *tmpLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];  
  54.         tmpLabel.layer.masksToBounds = YES;  
  55.         tmpLabel.layer.cornerRadius = 10;  
  56.         tmpLabel.backgroundColor = [UIColor redColor];  
  57.         [self.view addSubview:tmpLabel];  
  58.     }  
  59. }  
  60.   
  61. @end  


         运行代码:可以看到闪退,我们用iExplorer打开:

         

        导出error日志,我们可以看到:


[html] view plain copy
 print?
  1. Exception reason:NSRangeException  
  2. <span style="color:#FF0000;">Exception name:*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds for empty array</span>  
  3. Exception stack:(  
  4.     0   CoreFoundation                      0x2f2edfeb <redacted> + 154  
  5.     1   libobjc.A.dylib                     0x39b66ccf objc_exception_throw + 38  
  6.     2   CoreFoundation                      0x2f224a89 <redacted> + 176  
  7. <span style="color:#FF0000;"> 3   TestCrash                           0x000e8077 -[TestViewController crashTapped:] + 126</span>  
  8.     4   UIKit                               0x31b3f057 <redacted> + 90  
  9.     5   UIKit                               0x31b3eff7 <redacted> + 30  
  10.     6   UIKit                               0x31b3efd1 <redacted> + 44  
  11.     7   UIKit                               0x31b2a737 <redacted> + 374  
  12.     8   UIKit                               0x31b3ea4f <redacted> + 590  
  13.     9   UIKit                               0x31b3e721 <redacted> + 528  
  14.     10  UIKit                               0x31b396eb <redacted> + 758  
  15.     11  UIKit                               0x31b0e8ed <redacted> + 196  
  16.     12  UIKit                               0x31b0cf97 <redacted> + 7102  
  17.     13  CoreFoundation                      0x2f2b925b <redacted> + 14  
  18.     14  CoreFoundation                      0x2f2b872b <redacted> + 206  
  19.     15  CoreFoundation                      0x2f2b6f1f <redacted> + 622  
  20.     16  CoreFoundation                      0x2f221f0f CFRunLoopRunSpecific + 522  
  21.     17  CoreFoundation                      0x2f221cf3 CFRunLoopRunInMode + 106  
  22.     18  GraphicsServices                    0x3417a663 GSEventRunModal + 138  
  23.     19  UIKit                               0x31b6d16d UIApplicationMain + 1136  
  24.     20  TestCrash                           0x000e810d main + 116  
  25.     21  libdyld.dylib                       0x3a073ab7 <redacted> + 2  
  26. )  

太清楚了,对吧,下次启动应用程序的时候可以把这个error.log(这个名字我临时写的,用什么日期也可以的)上传。可以在日志中加上类似与友盟的  iphone 的UUID、Bundle ID 等等。


现在猜测一下,友盟是不是这么做的呢?

进入一个引用友盟sdk项目的根目录,打开mac终端输入命令 grep -r   NSSetUncaughtExceptionHandler .(这个点不能少或者绝对路径替换这个点),得到如下图:



真的就找到了,什么什么  matches。当然这只是猜测。

原创粉丝点击