iOS CrashLog分析

在程序开发的过程中,难免遇到各种崩溃情况。目前我了解到的崩溃信息收集有如下几种途径:参考

  1. iTunes Connect导出手机上传日志、
  2. 拿到用户手机使用 Xcode 导出、
  3. 使用第三方崩溃收集服务(如 Bugly、友盟等),
  4. 手动收集崩溃信息。

这篇文章主要介绍crash日志的分析,为下一篇手动收集和分析崩溃日志打下一些基础。

我们先看看最原始取到的崩溃日志是什么样子的

Incident Identifier: FD86E6F8-FBF4-4D70-97FF-144CFA95286B
CrashReporter Key:   406e631e757d2782d57d0283f97edd069a4b5974
Hardware Model:      iPhone8,1
Process:             tesApp [1058]
Path:                /private/var/containers/Bundle/Application/320EF082-7158-447F-9927-F0D52C16570F/tesApp.app/tesApp
Identifier:          com.test.tesApp
Version:             1 (2.0.0)
Code Type:           ARM-64 (Native)
Role:                Foreground
Parent Process:      launchd [1]
Coalition:           com.test.tesApp [925]

Date/Time:           2017-11-23 16:06:29.6264 +0800
Launch Time:         2017-11-23 16:05:25.2049 +0800
OS Version:          iPhone OS 11.1.2 (15B202)
Baseband Version:    4.00.01
Report Version:      104

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

Application Specific Information:
abort() called

Filtered syslog:
None found

Last Exception Backtrace:
0   CoreFoundation                    0x1835bdd04 __exceptionPreprocess + 124
1   libobjc.A.dylib                   0x18280c528 objc_exception_throw + 55
2   CoreFoundation                    0x183556bd4 _CFThrowFormattedException + 111
3   CoreFoundation                    0x1836058a8 -[__NSArrayI objectAtIndexedSubscript:] + 131
4   weidasheng_dev                    0x102d478b8 0x102d14000 + 211128
5   weidasheng_dev                    0x102d463f0 0x102d14000 + 205808
6   UIKit                             0x18cd2f93c 0x18c9e5000 + 3451196
7   UIKit                             0x18cd2fea0 0x18c9e5000 + 3452576
8   UIKit                             0x18cd0f9e4 0x18c9e5000 + 3320292
9   UIKit                             0x18cac54fc 0x18c9e5000 + 918780
10  UIKit                             0x18c9f22f8 0x18c9e5000 + 54008
11  QuartzCore                        0x1875abec8 -[CALayer layoutSublayers] + 183
12  QuartzCore                        0x1875affa8 CA::Layer::layout_if_needed+ 1187752 (CA::Transaction*) + 331
13  QuartzCore                        0x18751ea98 CA::Context::commit_transaction+ 592536 (CA::Transaction*) + 335
14  QuartzCore                        0x187544eb4 CA::Transaction::commit+ 749236 () + 539
15  QuartzCore                        0x187545cf4 CA::Transaction::observer_callback+ 752884 (__CFRunLoopObserver*, unsigned long, void*) + 91
16  CoreFoundation                    0x183565848 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 31
17  CoreFoundation                    0x183563200 __CFRunLoopDoObservers + 411
18  CoreFoundation                    0x1835637bc __CFRunLoopRun + 1291
19  CoreFoundation                    0x183483fb8 CFRunLoopRunSpecific + 435
20  GraphicsServices                  0x18531bf84 GSEventRunModal + 99
21  UIKit                             0x18ca582e8 0x18c9e5000 + 471784
22  weidasheng_dev                    0x102d22360 0x102d14000 + 58208
23  libdyld.dylib                     0x182fa656c start + 3

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib            0x00000001830d5348 __pthread_kill + 8
1   libsystem_pthread.dylib           0x00000001831e9344 pthread_kill$VARIANT$mp + 396
2   libsystem_c.dylib                 0x0000000183044fb8 abort + 140
3   libc++abi.dylib                   0x00000001827e4068 __cxa_bad_cast + 0
4   libc++abi.dylib                   0x00000001827fc568 std::__terminate(void (*)+ 107880 ()) + 44
5   libc++abi.dylib                   0x00000001827fc158 __cxa_rethrow + 144
6   libobjc.A.dylib                   0x000000018280c6e8 objc_exception_rethrow + 44
7   CoreFoundation                    0x0000000183484024 CFRunLoopRunSpecific + 544
8   GraphicsServices                  0x000000018531bf84 GSEventRunModal + 100
9   UIKit                             0x000000018ca582e8 0x18c9e5000 + 471784
10  weidasheng_dev                    0x0000000102d22360 0x102d14000 + 58208
11  libdyld.dylib                     0x0000000182fa656c start + 4

Thread 1 name:  com.apple.uikit.eventfetch-thread
Thread 1:
0   libsystem_kernel.dylib            0x00000001830b4bc4 mach_msg_trap + 8
1   libsystem_kernel.dylib            0x00000001830b4a3c mach_msg + 72
2   CoreFoundation                    0x0000000183565c74 __CFRunLoopServiceMachPort + 196
3   CoreFoundation                    0x0000000183563840 __CFRunLoopRun + 1424
4   CoreFoundation                    0x0000000183483fb8 CFRunLoopRunSpecific + 436
5   Foundation                        0x0000000183ead6e4 -[NSRunLoop+ 50916 (NSRunLoop) runMode:beforeDate:] + 304
6   Foundation                        0x0000000183eccafc -[NSRunLoop+ 178940 (NSRunLoop) runUntilDate:] + 96
7   UIKit                             0x000000018d5b72f4 0x18c9e5000 + 12395252
8   Foundation                        0x0000000183fae860 __NSThread__start__ + 996
9   libsystem_pthread.dylib           0x00000001831e831c _pthread_body + 308
10  libsystem_pthread.dylib           0x00000001831e81e8 _pthread_body + 0
11  libsystem_pthread.dylib           0x00000001831e6c28 thread_start + 4

Thread 2 name:  com.apple.NSURLConnectionLoader
Thread 2:
0   libsystem_kernel.dylib            0x00000001830b4bc4 mach_msg_trap + 8
1   libsystem_kernel.dylib            0x00000001830b4a3c mach_msg + 72
2   CoreFoundation                    0x0000000183565c74 __CFRunLoopServiceMachPort + 196
3   CoreFoundation                    0x0000000183563840 __CFRunLoopRun + 1424
4   CoreFoundation                    0x0000000183483fb8 CFRunLoopRunSpecific + 436
5   CFNetwork                         0x0000000183bee264 +[NSURLConnection+ 717412 (Loader) _resourceLoadLoop:] + 404
6   Foundation                        0x0000000183fae860 __NSThread__start__ + 996
7   libsystem_pthread.dylib           0x00000001831e831c _pthread_body + 308
8   libsystem_pthread.dylib           0x00000001831e81e8 _pthread_body + 0
9   libsystem_pthread.dylib           0x00000001831e6c28 thread_start + 4
...

Thread 0 crashed with ARM Thread State (64-bit):
    x0: 0x0000000000000000   x1: 0x0000000000000000   x2: 0x0000000000000000   x3: 0x00000001c02e7fb1
    x4: 0x00000001828023de   x5: 0x000000016d0eb920   x6: 0x000000000000006e   x7: 0x00000001c4112480
    x8: 0x0000000008000000   x9: 0x0000000004000000  x10: 0x00000001831ed62c  x11: 0x0000000000000001
   x12: 0xffffffffffffffff  x13: 0x0000000000000001  x14: 0x00003b0000003b00  x15: 0x0000000000000010
   x16: 0x0000000000000148  x17: 0x00000000ffffffff  x18: 0x0000000000000000  x19: 0x0000000000000006
   x20: 0x00000001b4168b80  x21: 0x000000016d0eb920  x22: 0x0000000000000303  x23: 0x00000001b4168c60
   x24: 0x00000001c000a830  x25: 0x0000000000000000  x26: 0x0000000000000001  x27: 0x0000000000000000
   x28: 0x000000016d0ebb18   fp: 0x000000016d0eb880   lr: 0x00000001831e9344
    sp: 0x000000016d0eb850   pc: 0x00000001830d5348 cpsr: 0x00000000

Binary Images:
0x102d14000 - 0x10368ffff weidasheng_dev arm64  <9599d010fc953cdcacf0298f33f54d20> /var/containers/Bundle/Application/320EF082-7158-447F-9927-F0D52C16570F/weidasheng_dev.app/weidasheng_dev
0x104230000 - 0x10426ffff dyld arm64  <92368d6f78863cc88239f2e3ec79bba8> /usr/lib/dyld
….

EOF
分析日志

分析log日志参考,我这里稍微总结下。
我这里直接把我目前一般找crash原因的模块展示出来,其他的就留待各位自己去研究了,分别是设备和crash信息、异常信息、线程信息
1、首先是设备和crash信息


Incident Identifier: F3573A...E2F244A              //crash的id
CrashReporter Key:   cc2298...es77eeb              //crash的设备id
Hardware Model:      iPhone7,2                     //手机型号
Process:             [AppName] [1816]              //APP的名字[进程的id]
Path:                /private/.../Application...   //APP的位置
Identifier:          com....                       //bundle ID
Version:             14 (2.3.5)                    //版本号
Code Type:           ARM-64 (Native)               //app的CPU类型
Parent Process:      launchd [1]

Date/Time:           2015-10-26 15:03:29.29 +0800    //crash发生时间
Launch Time:         2015-10-26 14:58:28.28 +0800    //进入应用时间
OS Version:          iOS 9.1 (13B143)                //iOS版本
Report Version:      105

当你有大量的crash文件的时候,你就可以对crash文件里面的 Hardware Model,Version , OS Version等进行分类,就可以获知到很多信息。进行图像化展示

2、其次是异常信息

Exception Type:  EXC_BAD_ACCESS (SIGABRT)                      //异常的类型
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000118  //异常子类型
Triggered by Thread:  0                    //异常发生的线程(0为主线程,其他为子线程)

3、线程信息


Last Exception Backtrace:
0   CoreFoundation                  0x182780f48 __exceptionPreprocess + 124
1   libobjc.A.dylib                 0x197333f80 objc_exception_throw + 56
2   CoreFoundation                  0x182780e90 +[NSException raise:format:] + 120
3   [AppName]                           0x100c42a40 UmengSignalHandler + 144
4   libsystem_platform.dylib        0x197d6193c _sigtramp + 52
5   [AppName]                           0x1005d9f38 CScopePtr::operator IAVGAudioLogic*() (xprefc.h:165)
6   [AppName]                           0x1005d3b8c tencent::av::AVRoomMultiImpl::GetAudioLogic() (av_room_multi_impl.h:119)
7   [AppName]                           0x10057076c tencent::av::AVAudioCtrlImpl::SetAudioOutputMode(int) (av_audio_ctrl_impl.cpp:443)
8   [AppName]                           0x10044dc3c -[AVBasicManager changeSpeakerMode:] (AVManager.mm:525)
9   [AppName]                           0x100296e1c -[KTQAVRoom enableSpeakerMode:] (KTQAVRoom.m:345)
10  [AppName]                           0x1002970d0 -[KTQAVRoom settingSpeaker:] (KTQAVRoom.m:362)
11  [AppName]                           0x1003d5464 -[KTChatView onAudioNotificationReceived:] (KTChatView.m:685)

什么情况下会产生崩溃日志?

两种主要情况会产生崩溃日志:

  1. 应用违反操作系统规则。
  2. 应用中有Bug。
1.违反iOS规则

违反iOS规则包括在启动、恢复、挂起、退出时watchdog超时、用户强制退出和低内存终止。

Watchdog 超时机制

退出应用时,应用不会立即终止,而是退到后台。但是,如果你的应用响应不够快,操作系统有可能会终止你的应用,并产生一个崩溃日志。这些事件与下列UIApplicationDelegate方法相对应:
application:didFinishLaunchingWithOptions:
applicationWillResignActive:
applicationDidEnterBackground:
applicationWillEnterForeground:
applicationDidBecomeActive:
applicationWillTerminate:

上面所有这些方法,应用只有有限的时间去完成处理。如果花费时间太长,操作系统将终止应用

用户强制退出

iOS 4.x开始支持多任务。如果应用阻塞界面并停止响应, 用户可以通过在主屏幕上双击Home按钮,并上滑来终止应用。此时,操作应用将生成一个崩溃日志。

注意: 双击Home按钮后,你将看到运行过的所有应用。那些应用不一定是正在运行,也不一定是被挂起。

通常,用户点击Home按钮时,应用将在后台保留约10分钟,然后操作系统自动将其终止。 所以双击Home按钮显示的应用列表只是表明那是一系列过去打开过的应用。删除那些应用的图标不会产生任何崩溃日志。

低内存终止

在前台运行的应用拥有访问和使用内存的最高优化级。然而,这并不意味着该应用能使用设备的所有可用内存 ——每个应用只能使用一部分可用内存。

当内存使用达到一定程度时,操作系统将发出一个 UIApplicationDidReceiveMemoryWarningNotification 通知。同时,调用 didReceiveMemoryWarning 方法。

此时,为了让应用继续正常运行,操作系统开始终止在后台的其他应用以释放一些内存。所有后台应用被终止后,如果你的应用还需要更多内存,操作系统会将你的应用也终止掉,并产生一个崩溃日志。而在这种情况下被终止的后台应用,不会产生崩溃日志。另外,在极短时间内分配一大块内存将给系统内存带来巨大负担。也会产生内存警告的通知。

2.应用中有Bug

但是大多数情况我们会更关心由于代码原因而导致的崩溃。常见的错误type和code码有

1、Exception Type

1)EXC_BAD_ACCESS

此类型的Excpetion是我们最长碰到的Crash,通常用于访问了不改访问的内存导致。一般EXC_BAD_ACCESS后面的"()"还会带有补充信息。

SIGSEGV: 通常由于重复释放对象导致,这种类型在切换了ARC以后应该已经很少见到了。

SIGABRT: 收到Abort信号退出,通常Foundation库中的容器为了保护状态正常会做一些检测,例如插入nil到数组中等会遇到此类错误。

SEGV:(Segmentation Violation),代表无效内存地址,比如空指针,未初始化指针,栈溢出等;

SIGBUS:总线错误,与 SIGSEGV 不同的是,SIGSEGV 访问的是无效地址,而 SIGBUS 访问的是有效地址,但总线访问异常(如地址对齐问题)

SIGILL:尝试执行非法的指令,可能不被识别或者没有权限

2)EXC_BAD_INSTRUCTION

此类异常通常由于线程执行非法指令导致

3)EXC_ARITHMETIC
除零错误会抛出此类异常

2、常见错误码

0x8badf00d: 读做 “ate bad food”! (把数字换成字母,是不是很像 :p)该编码表示应用是因为发生watchdog超时而被iOS终止的。 通常是应用花费太多时间而无法启动、终止或响应用系统事件。
0xbad22222: 该编码表示 VoIP 应用因为过于频繁重启而被终止。
0xdead10cc: 读做 “dead lock”!该代码表明应用因为在后台运行时占用系统资源,如通讯录数据库不释放而被终止 。
0xdeadfa11: 读做 “dead fall”! 该代码表示应用是被用户强制退出的。根据苹果文档, 强制退出发生在用户长按开关按钮直到出现 “滑动来关机”, 然后长按 Home按钮。强制退出将产生 包含0xdeadfa11 异常编码的崩溃日志, 因为大多数是强制退出是因为应用阻塞了界面。

(注意: 在后台任务列表中关闭已挂起的应用不会产生崩溃日志。 一旦应用被挂起,它何时被终止都是合理的。所以不会产生崩溃日志。)

低内存崩溃日志与其他类型的崩溃日志很不一样,它们不指向特定的文件和代码行。相反,它们画出了闪退时设备上的内存使用情况的图表。

符号化Symbolication

第一次看到崩溃日志上的回溯时,你或许会觉得它没什么意义。把它转化成可读性更强的样式。这个过程称之为符号化

我们习惯使用方法名和行数,而非像这样的神秘位置:
当前代码行地址 = 当前地址 + 地址偏移量,地址偏移量为十进制数值
如果相同的crash,相同位置后面的地址偏移量相同,前面两个数值可能会有变动

符号化前

4   weidasheng_dev                    0x102d478b8 0x102d14000 + 211128

符号化后

iOS CrashLog分析_第1张图片
符号化后

符号化的常用方法

1.symbolicatecrash

symbolicatecrash是xcode的一个符号化crash log的命令行工具。使用方法也就是导出.crash文件(crash log)和找到.dsYM文件,然后进行分析。

如何使用查看[iOS]使用symbolicatecrash分析crash文件

2.还有命令行工具atos

如果你有多个“.ipa”文件,多个".dSYMB"文件,你并不太确定到底“dSYM”文件对应哪个".ipa"文件,那么,这个方法就非常适合你。

特别当你的应用发布到多个渠道的时候,你需要对不同渠道的crash文件,写一个自动化的分析脚本的时候,这个方法就极其有用。

简单使用方法命令行工具atos

3.第三方小工具.dsYM分析。(我平时就是用这个方法,比较简单)

具体可参考文章dSYM 文件分析工具

你可能感兴趣的:(iOS CrashLog分析)