• 获取 iOS crash log


    在ios开发过程中,经常会遇到应用在开发过程中或者自己测试时不会有问题。而在安装到别人设备上,或者上传应用商店被别人下载的时候,总是被抱怨程序不定期的crash,真的很令人懊恼!

    获取 iOS crash log

    这时iOS crash log 派上用场了,程序的大多数crash都会记录在用户的手机中,获取crash log的方法有两种:

    1. 用户把设备连接到电脑上,打开xcode-window-organizer,选中Devices-当前连接设备-Device Log,就可以查看所有当前设备的crash log,这个时候打开每一份crash的时候,发现这些文件的部分地址都会被转换成,类名,方法名和行号等。设备上的日志只用刚刚查看过都会被同步到organizer种,在LIBRARY下的Device Log可以查看

    2. 如果你的应用已经上架,那么开发者可以通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash日志。不过这并不是100%有效的,而且大多数开发者并不依赖于此,因为这需要用户设备同意上传相关信息,详情可参见iOS: Providing Apple with diagnostics and usage information摘要。

    解析ios Crash Log(解析全部文件)

    如果在Itunes Connect 得到的Log文件打开查看都是十六进制的地址

    复制代码
    Incident Identifier: 70B8BA67-3342-4354-8EC5-23B361C5A02A
    CrashReporter Key:   457198753f9cf1ae3862aef8ce49127acfd84425
    Hardware Model:      iPod5,1
    Process:             TestTransform [510]
    Path:                /var/mobile/Applications/037726D5-5DAA-4E02-9CD1-68E0865CF4CF/TestTransform.app/TestTransform
    Identifier:          com.TestTransform
    Version:             1.0 (1.0)
    Code Type:           ARM (Native)
    Parent Process:      launchd [1]
    
    Date/Time:           2014-04-10 09:57:27.961 +0800
    OS Version:          iOS 7.1 (11D167)
    Report Version:      104
    
    Exception Type:  EXC_CRASH (SIGABRT)
    Exception Codes: 0x0000000000000000, 0x0000000000000000
    Triggered by Thread:  2
    
    Last Exception Backtrace:
    (0x2e71dfce 0x38e66cca 0x2e654ac4 0x57130 0x3934e82e 0x39355ad2 0x39355d24 0x39490bce 0x39490a94)
    
    Thread 0:
    0   libsystem_kernel.dylib            0x39416a58 0x39416000 + 2648
    1   libsystem_kernel.dylib            0x39416854 0x39416000 + 2132
    2   CoreFoundation                    0x2e6e8896 0x2e64a000 + 649366
    3   CoreFoundation                    0x2e6e7002 0x2e64a000 + 643074
    4   CoreFoundation                    0x2e651f4a 0x2e64a000 + 32586
    5   CoreFoundation                    0x2e651d2e 0x2e64a000 + 32046
    6   GraphicsServices                  0x3357365e 0x3356a000 + 38494
    7   UIKit                             0x30f9d168 0x30f2f000 + 450920
    8   TestTransform                     0x00061c5c 0x4f000 + 76892
    9   libdyld.dylib                     0x39373ab4 0x39372000 + 6836
    
    Thread 1:
    0   libsystem_kernel.dylib            0x39416808 0x39416000 + 2056
    1   libdispatch.dylib                 0x39358078 0x3934d000 + 45176
    2   libdispatch.dylib                 0x39357dfe 0x3934d000 + 44542
    
    Thread 2 Crashed:
    0   libsystem_kernel.dylib            0x394291f0 0x39416000 + 78320
    1   libsystem_pthread.dylib           0x39493792 0x39490000 + 14226
    2   libsystem_c.dylib                 0x393d9fd8 0x39391000 + 298968
    3   libc++abi.dylib                   0x38708cd2 0x38708000 + 3282
    4   libc++abi.dylib                   0x387216e0 0x38708000 + 104160
    5   libobjc.A.dylib                   0x38e66f62 0x38e63000 + 16226
    6   libc++abi.dylib                   0x3871f1c4 0x38708000 + 94660
    7   libc++abi.dylib                   0x3871ea18 0x38708000 + 92696
    8   libobjc.A.dylib                   0x38e66d9e 0x38e63000 + 15774
    9   CoreFoundation                    0x2e654ac4 0x2e64a000 + 43716
    10  TestTransform                     0x00057132 0x4f000 + 33074
    11  libdispatch.dylib                 0x3934e830 0x3934d000 + 6192
    12  libdispatch.dylib                 0x39355ad2 0x3934d000 + 35538
    13  libdispatch.dylib                 0x39355d24 0x3934d000 + 36132
    14  libsystem_pthread.dylib           0x39490bd0 0x39490000 + 3024
    15  libsystem_pthread.dylib           0x39490a94 0x39490000 + 2708
    
    Thread 3:
    0   libsystem_kernel.dylib            0x39429c70 0x39416000 + 81008
    1   libsystem_pthread.dylib           0x39490bda 0x39490000 + 3034
    2   libsystem_pthread.dylib           0x39490a94 0x39490000 + 2708
    
    Thread 2 crashed with ARM Thread State (32-bit):
        r0: 0x00000000    r1: 0x00000000      r2: 0x00000000      r3: 0x393ccaa9
        r4: 0x00000006    r5: 0x001c5000      r6: 0x00000000      r7: 0x001c41a4
        r8: 0x16e261d0    r9: 0x00000001     r10: 0x00000000     r11: 0x00000000
        ip: 0x00000148    sp: 0x001c4198      lr: 0x39493797      pc: 0x394291f0
      cpsr: 0x00000010
    
    Binary Images:
    0x4f000 - 0x62fff TestTransform armv7  <12a331e98ea13836b33483de64c3b1fc> /var/mobile/Applications/037726D5-5DAA-4E02-9CD1-68E0865CF4CF/TestTransform.app/TestTransform
    0x2bec3000 - 0x2bee3fff dyld armv7  <651a31c39f71311f965f8ac44de02c88> /usr/lib/dyld
    0x2d6e1000 - 0x2d6e1fff Accelerate armv7  <0424978b39f037a7b3bf9aad5b34a5b3> /System/Library/Frameworks/Accelerate.framework/Accelerate
    ......
    复制代码

    如果想查看文件的庐山真面目,需要找出在上传应用时所发送的.app和.DSYM文件,切记每次发送新版本都要保留这两个文件,不然没有办法解析Crash Log的。可以先把这两个文件拷贝到桌面的某一个文件夹中,然后把.crash的文件也拷贝的同一个文件夹下。

    这一解析过程需要使用Symbolicatecrash来完成,首先要找到Symbolicatecrash文件,xcode5.0在 
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/ 
    Symbolicatecrash文件独立于Xcode,可以拷到刚才放crash log的文件夹中使用,在开始解析之前需要先进行一些校验:
    1. 查看xx.app文件的uuid的方法,在命令行中输入:

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

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

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

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

    只有三者的uuid相同才能解析.crash文件,然后在命令行输入:

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

    这样可以将.crash日志转换成test.log,test.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为:

    复制代码
    Incident Identifier: 70B8BA67-3342-4354-8EC5-23B361C5A02A
    CrashReporter Key:   457198753f9cf1ae3862aef8ce49127acfd84425
    Hardware Model:      iPod5,1
    Process:             TestTransform [510]
    Path:                /var/mobile/Applications/037726D5-5DAA-4E02-9CD1-68E0865CF4CF/TestTransform.app/TestTransform
    Identifier:          com.TestTransform
    Version:             1.0 (1.0)
    Code Type:           ARM (Native)
    Parent Process:      launchd [1]
    
    Date/Time:           2014-04-10 09:57:27.961 +0800
    OS Version:          iOS 7.1 (11D167)
    Report Version:      104
    
    Exception Type:  EXC_CRASH (SIGABRT)
    Exception Codes: 0x0000000000000000, 0x0000000000000000
    Triggered by Thread:  2
    
    Last Exception Backtrace:
    0   CoreFoundation                    0x2e71dfce __exceptionPreprocess + 126
    1   libobjc.A.dylib                   0x38e66cca objc_exception_throw + 34
    2   CoreFoundation                    0x2e654ac4 -[__NSArrayI objectAtIndex:] + 172
    3   TestTransform                     0x00057130 __29-[ViewController aaaaaaaaaa:]_block_invoke (ViewController.m:193)
    4   libdispatch.dylib                 0x3934e82e _dispatch_call_block_and_release + 6
    5   libdispatch.dylib                 0x39355ad2 _dispatch_root_queue_drain + 218
    6   libdispatch.dylib                 0x39355d24 _dispatch_worker_thread2 + 52
    7   libsystem_pthread.dylib           0x39490bce _pthread_wqthread + 294
    8   libsystem_pthread.dylib           0x39490a94 start_wqthread + 4
    
    
    Thread 0:
    0   libsystem_kernel.dylib            0x39416a58 mach_msg_trap + 20
    1   libsystem_kernel.dylib            0x39416854 mach_msg + 44
    2   CoreFoundation                    0x2e6e8896 __CFRunLoopServiceMachPort + 150
    3   CoreFoundation                    0x2e6e7002 __CFRunLoopRun + 850
    4   CoreFoundation                    0x2e651f4a CFRunLoopRunSpecific + 518
    5   CoreFoundation                    0x2e651d2e CFRunLoopRunInMode + 102
    6   GraphicsServices                  0x3357365e GSEventRunModal + 134
    7   UIKit                             0x30f9d168 UIApplicationMain + 1132
    8   TestTransform                     0x00061c5c main (main.m:16)
    9   libdyld.dylib                     0x39373ab4 start + 0
    
    Thread 1:
    0   libsystem_kernel.dylib            0x39416808 kevent64 + 24
    1   libdispatch.dylib                 0x39358078 _dispatch_mgr_invoke + 228
    2   libdispatch.dylib                 0x39357dfe _dispatch_mgr_thread$VARIANT$mp + 34
    
    Thread 2 Crashed:
    0   libsystem_kernel.dylib            0x394291f0 __pthread_kill + 8
    1   libsystem_pthread.dylib           0x39493792 pthread_kill + 54
    2   libsystem_c.dylib                 0x393d9fd8 abort + 72
    3   libc++abi.dylib                   0x38708cd2 abort_message + 70
    4   libc++abi.dylib                   0x387216e0 default_terminate_handler() + 248
    5   libobjc.A.dylib                   0x38e66f62 _objc_terminate() + 190
    6   libc++abi.dylib                   0x3871f1c4 std::__terminate(void (*)()) + 76
    7   libc++abi.dylib                   0x3871ea18 __cxa_throw + 112
    8   libobjc.A.dylib                   0x38e66d9e objc_exception_throw + 246
    9   CoreFoundation                    0x2e654ac4 -[__NSArrayI objectAtIndex:] + 172
    10  TestTransform                     0x00057132 __29-[ViewController aaaaaaaaaa:]_block_invoke (ViewController.m:193)
    11  libdispatch.dylib                 0x3934e830 _dispatch_call_block_and_release + 8
    12  libdispatch.dylib                 0x39355ad2 _dispatch_root_queue_drain + 218
    13  libdispatch.dylib                 0x39355d24 _dispatch_worker_thread2 + 52
    14  libsystem_pthread.dylib           0x39490bd0 _pthread_wqthread + 296
    15  libsystem_pthread.dylib           0x39490a94 start_wqthread + 4
    
    Thread 3:
    0   libsystem_kernel.dylib            0x39429c70 __workq_kernreturn + 8
    1   libsystem_pthread.dylib           0x39490bda _pthread_wqthread + 306
    2   libsystem_pthread.dylib           0x39490a94 start_wqthread + 4
    
    Thread 2 crashed with ARM Thread State (32-bit):
        r0: 0x00000000    r1: 0x00000000      r2: 0x00000000      r3: 0x393ccaa9
        r4: 0x00000006    r5: 0x001c5000      r6: 0x00000000      r7: 0x001c41a4
        r8: 0x16e261d0    r9: 0x00000001     r10: 0x00000000     r11: 0x00000000
        ip: 0x00000148    sp: 0x001c4198      lr: 0x39493797      pc: 0x394291f0
      cpsr: 0x00000010
    
    Binary Images:
    0x4f000 - 0x62fff TestTransform armv7  <12a331e98ea13836b33483de64c3b1fc> /var/mobile/Applications/037726D5-5DAA-4E02-9CD1-68E0865CF4CF/TestTransform.app/TestTransform
    0x2bec3000 - 0x2bee3fff dyld armv7  <651a31c39f71311f965f8ac44de02c88> /usr/lib/dyld
    0x2d6e1000 - 0x2d6e1fff Accelerate armv7  <0424978b39f037a7b3bf9aad5b34a5b3> /System/Library/Frameworks/Accelerate.framework/Accelerate
    ......
    复制代码

    这时候发现之前的一些行首为项目名 后面的地址变成的方面调用+行号。

    解析ios Crash Log(根据地址解析内容)

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

    $ xcrun atos -o xxx.app/xxx -arch armv7 0x38ad42f9 0x38ad42f9 0x38ad42f9(多个16进制地址,使用空格分开)---方法一
    $ dwarfdump -–lookup 0x000036d2 -–arch armv6 xxx.app.dSYM ---方法二

     如果根据以上方法操作,均提示找不到地址的话,可以使用必杀了:

    比如查找以下内容所对应的地址:
    (当前代码行地址 = 当前地址 + 地址偏移量,地址偏移量为十进制数值,公式是这样写的,但不知道具体表达是不是这个意思,如果相同的crash,相同位置后面的地址偏移量相同,前面两个数值可能会有变动)

    10  TestTransform                     0x00057132 0x4f000 + 33074

    1.先说第一种比较简单的方法利用 "当前地址" 和 "当前代码行地址"

    复制代码
    $ xcrun atos -o TestTransform.app/TestTransform -l 0x3d000 0x0004fc5c
    //输出结果:
    baidudeMacBook-Pro:1 baidu$ xcrun atos -o /Users/baidu/Desktop/1/TestTransform.app/TestTransform -l 0x3d000 0x0004fc5c
    got symbolicator for /Users/baidu/Desktop/1/TestTransform.app/TestTransform, base address 4000
    main (in TestTransform) (main.m:16)
    复制代码

    2. 第二种相对复杂一点,涉及到地址的偏移,使用首先查看起始地址,即使每次iOS app启动都会加载(main module)主模块在不同的内存地址,但是dSYM文件假设你的main module加载在地址0x1000(大多数情况是这个,也有0x4000的)。

    获取此地址的方法:

    $ otool -arch armv7 -l /Users/cnstar-tech/crash/xxx.app/xxx  | grep -B 1 -A 10 "LC_SEGM" | grep -B 3 -A 8 "__TEXT"

    调用以上方法返回结果如下:

    复制代码
    Load command 1
          cmd LC_SEGMENT
      cmdsize 600
      segname __TEXT
       vmaddr 0x00004000
       vmsize 0x00014000
      fileoff 0
     filesize 81920
      maxprot 0x00000005
     initprot 0x00000005
       nsects 8
        flags 0x0
    复制代码

    看到vmaddr显示为0x00004000。

    然后查看  "TestTransform 0x00057132 0x4f000 + 33074"  使用 起始地址+地址偏移量如:
    0x4000 + 33074 = 0xc132   (注意:前面为前面为16进制后面为10进制相加,要都转换成10进制相加,把得出的结果转换成16进制)
    就可以使用 "0xc132" 地址查看内容了:

    复制代码
    //方法一:
    $ dwarfdump --lookup 0xc132 --arch armv7 TestTransform.app.DSYM
    
    //输出结果:
    ----------------------------------------------------------------------
     File: TestTransform.app.DSYM/Contents/Resources/DWARF/TestTransform (armv7)
    ----------------------------------------------------------------------
    Looking up address: 0x000000000000c132 in .debug_info... found!
    
    0x00003947: Compile Unit: length = 0x00007b6e  version = 0x0002  abbr_offset = 0x00000000  addr_size = 0x04  (next CU at 0x0000b4b9)
    
    0x00003952: TAG_compile_unit [1] *
                 AT_producer( "Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)" )
                 AT_language( DW_LANG_ObjC )
                 AT_name( "/Users/baidu/Desktop/TestTransform/TestTransform/ViewController.m" )
                 AT_low_pc( 0x0000a950 )
                 AT_stmt_list( 0x0000089f )
                 AT_comp_dir( "/Users/baidu/Desktop/TestTransform" )
                 AT_APPLE_major_runtime_vers( 0x02 )
    
    0x00003c22:     TAG_subprogram [39] *
                     AT_name( "__29-[ViewController aaaaaaaaaa:]_block_invoke" )
                     AT_decl_file( "/Users/baidu/Desktop/TestTransform/TestTransform/ViewController.m" )
                     AT_decl_line( 191 )
                     AT_prototyped( 0x01 )
                     AT_APPLE_isa( 0x01 )
                     AT_accessibility( DW_ACCESS_public )
                     AT_low_pc( 0x0000c09c )
                     AT_high_pc( 0x0000c182 )
                     AT_frame_base( r7 )
    
    0x00003c46:         TAG_lexical_block [34] *
                         AT_low_pc( 0x0000c0d6 )
                         AT_high_pc( 0x0000c17e )
    Line table dir : '/Users/baidu/Desktop/TestTransform/TestTransform'
    Line table file: 'ViewController.m' line 193, column 0 with start address 0x000000000000c11e
    
    Looking up address: 0x000000000000c132 in .debug_frame... found!
    
    0x00000160: FDE
            length: 0x0000000c
       CIE_pointer: 0x00000000
        start_addr: 0x0000c09c __29-[ViewController aaaaaaaaaa:]_block_invoke
        range_size: 0x000000e6 (end_addr = 0x0000c182)
      Instructions: 0x0000c09c: CFA=4294967295+4294967295
    
    //方法二:
    $ xcrun atos -o /Users/baidu/Desktop/1/TestTransform.app/TestTransform 0xc132
    
    //输出结果:
    __29-[ViewController aaaaaaaaaa:]_block_invoke (in TestTransform) (ViewController.m:193)
    复制代码

    分析ios Crash Log:

    Incident Identifier:当前crash的 id,可以区分不同的crash事件
    CrashReporter Key: 当前设备的id,可以判断crash在某一设备上出现的频率
    Hardware Model:     设备型号
    Process:                 当前应用的名称,后面中括号中为当前的应用在系统中的进程id
    Path:                     当前应用在设备中的路径
    Identifier:              bundle id
    Version:                 应用版本号
    Code Type:            (还不清楚)
    Date/Time:             crash事件 时间
    OS Version:            当前系统版本
    Exception Type:       异常类型
    Exception Codes:     异常出错的代码(常见代码有以下几种)
                                 0x8badf00d错误码:Watchdog超时,意为“ate bad food”。
                                 0xdeadfa11错误码:用户强制退出,意为“dead fall”。
                                 0xbaaaaaad错误码:用户按住Home键和音量键,获取当前内存状态,不代表崩溃。
                                 0xbad22222错误码:VoIP应用(因为太频繁?)被iOS干掉。
                                 0xc00010ff错误码:因为太烫了被干掉,意为“cool off”。
                                 0xdead10cc错误码:因为在后台时仍然占据系统资源(比如通讯录)被干掉,意为“dead lock”。

    Triggered by Thread:     在某一个线程出了问题导致crash,Thread 0  为主线程、其它的都为子线程
    Last Exception Backtrace:     最后异常回溯,一般根据这个代码就能找到crash的具体问题
     

    Crash Log分类:

    如果所有的CrashLog已经被采集下来了,为了避免重复解决相同的bug,这个时候就需要所有的CrashLog分类,通过上面已有的信息,就可以对CrashLog做如下的分类控制:

    1. 通过设备id查找当前设备上出现的crash(通过CrashReporter Key);
    2. 查找所有在iphone5上出现的crash(通过Hardware Model);
    3. 查找所有在ios7.1上出现的crash(通过OS Version);
    4. 查找所有在应用1.0版本上出现的crash(通过 Version);
    5. 查看在某一个时间段内出现的crash(通过 Date/Time);
    6. 查找所有因为内存问题出现的crash (通过 Exception Type);
    7. 查找在主线程出现crash的问题(Triggered by Thread  == 0);
    8. 对上述条件的组合查询;

    当然做主要的时对crash的分类,判断两个crash是不是属于同一个(或同一类)crash:
    1. 通过Triggered by Thread字段判断当前两个crash是不是同时都在主线程(或同时都在子线程);
    2. 判断当前两个crash的Exception Type和Exception Codes是否相同;
    3. 如果有Last Exception Backtrace:字段,执行 4. 5 步;
    4. 可以先判断Last Exception Backtrace:栈上的行数是不是一样(如果在解析之前,每一行用一个地址表示),不一样则认为不是同一个crash;

    解析前:

    Last Exception Backtrace:
    (0x2e71dfce 0x38e66cca 0x2e654ac4 0x57130 0x3934e82e 0x39355ad2 0x39355d24 0x39490bce 0x39490a94)

    解析后:

    复制代码
    Last Exception Backtrace:
    0   CoreFoundation                    0x2e71dfce __exceptionPreprocess + 126
    1   libobjc.A.dylib                   0x38e66cca objc_exception_throw + 34
    2   CoreFoundation                    0x2e654ac4 -[__NSArrayI objectAtIndex:] + 172
    3   TestTransform                     0x00057130 __29-[ViewController aaaaaaaaaa:]_block_invoke (ViewController.m:193)
    4   libdispatch.dylib                 0x3934e82e _dispatch_call_block_and_release + 6
    5   libdispatch.dylib                 0x39355ad2 _dispatch_root_queue_drain + 218
    6   libdispatch.dylib                 0x39355d24 _dispatch_worker_thread2 + 52
    7   libsystem_pthread.dylib           0x39490bce _pthread_wqthread + 294
    8   libsystem_pthread.dylib           0x39490a94 start_wqthread + 4
    复制代码

    5. 先由第一个地址开始比较逐个比较(一般最开始几行和最后几行都是调用系统函数,所以地址都是一样的),直到发现某一个地址不一样,使用dwarfdump命令分别将两个地址解析。得到两个crash当前调用的方法名称和分别位于文件的行号,通过得到的信息在进行比较,然后终止比较,如果一样,则认为当前两个crash为同一原因,对比结束;
    6. 如果没有Last Exception Backtrace:字段,执行 7. 8. 步;
    7. 先通过Triggered by Thread字段找到两个crashLog分别对应的栈,比较栈上的行数是不是一样,不一样则认为不是同一个crash;
    8. 每一行对应一个地址,先由第一个地址开始比较(一般最开始几行和最后几行都是调用系统函数,所以地址都是一样的),直到发现某一个地址不一样,使用dwarfdump命令分别将两个地址解析。得到两个crash当前调用的方法名称和分别位于文件的行号,通过得到的信息在进行比较,然后终止比较,如果一样,则认为当前两个crash为同一原因,对比结束;

  • 相关阅读:
    单选按钮控件(Ridio Button)的使用
    带属性页的对话框
    异常处理与MiniDump详解(4) MiniDump
    单片机与嵌入式 以及ARM DSP FPGA 几个概念的理解
    VC更换图标文件
    http://user.qzone.qq.com/2413264738/2
    安装包安装 执行有相对路径的程序不能正确运行
    如何将 jar 包导入Maven 本地仓库
    19、访问者设计模式
    11、装饰器模式
  • 原文地址:https://www.cnblogs.com/iosblogx/p/4882116.html
Copyright © 2020-2023  润新知