如何查看iOS已上架APP的崩溃情况以及定位crash代码行

一、先分析app的崩溃的分布情况 这个需要有(iTunes connect账号),通过分析我们可以查看到自己的app奔溃主要发生在那些机型上。

二、打开xcode,下载崩溃日志,直接定位出问题代码行

1、打开xcode 先要下载崩溃日志  Window -> Organizer

2、选择crashes

3、查看相应版本的崩溃日志

4、点击对应的崩溃日志,后面会出现一个箭头,点击箭头就会进入到Xcode中对应的代码行,就可以根据自己的程序逻辑做出相应修改。

注意:

旧的iTunes Connect上可以查看崩溃日志,但新版已经不能查看崩溃日志了,只能在你的xcode上来查看

什么是崩溃日志

iOS设备上的应用闪退时,操作系统会生成一个崩溃报告,也叫崩溃日志。

崩溃日志上有很多有用的信息,包括应用是什么情况下闪退的。通常,上面有每个正在执行线程的完整堆栈跟踪信息,所以你能从中了解到闪退时各线程都在做什么,并分辨出闪退发生在哪个线程上。

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

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

1.应用违反操作系统规则

2.应用中有Bug

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

watchdog超时机制

从iOS 4.x开始,退出应用时,应用不会立即终止,而是退到后台。但是,如果你的应用响应不够快,操作系统有可能会终止你的应用,并产生一个崩溃日志,这些事情与下列UIApplicationDelegate方法相对应:

application:didFinishLaunchingWithOptions:

applicationWillResignActive:

applicationDidEnterBackground:

applicationWillEnterForeground:

applicationDidBecomeActive:

applicationWillTerminate:

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

重点:如果没有把需要花费时间比较长的操作,如网络访问,放在后台线程上就很容易发生这种情况。

崩溃日志解读:

1.UIKit开头应该是无法定位的错误,有红色标识的那一行就是错误信息


崩溃日志的实例

// 1: 进程信息

Incident Identifier: 30E46451-53FD-4965-896A-457FC11AD05F

CrashReporter Key:  5a56599d836c4f867f6eec76afee451bf9ae5f31

Hardware Model:      iPhone4,1

Process:        Rage Masters [4155]

Path:            /var/mobile/Applications/A5635B22-F5EF-4CEB-94B6-FE158D885014/Rage Masters.app/Rage Masters

Identifier:      Rage Masters

Version:        ??? (???)

Code Type:      ARM (Native)

Parent Process:  launchd [1]

// 2: 基本信息

Date/Time:      2012-10-17 21:39:06.967 -0400

OS Version:      iOS 6.0 (10A403)

Report Version:  104

// 3: 异常

Exception Type:  00000020

Exception Codes: 0x000000008badf00d

Highlighted Thread:  0

// 4: 线程回溯

Thread 0 name:  Dispatch queue: com.apple.main-thread

Thread 0:

0  libsystem_kernel.dylib        0x327f2eb4 mach_msg_trap + 20

1  libsystem_kernel.dylib        0x327f3048 mach_msg + 36

2  CoreFoundation                0x36bd4040 __CFRunLoopServiceMachPort + 124

3  CoreFoundation                0x36bd2d9e __CFRunLoopRun + 878

4  CoreFoundation                0x36b45eb8 CFRunLoopRunSpecific + 352

5  CoreFoundation                0x36b45d44 CFRunLoopRunInMode + 100

6  CFNetwork                    0x32ac343e CFURLConnectionSendSynchronousRequest + 330

7  Foundation                    0x346e69ba +[NSURLConnection sendSynchronousRequest:returningResponse:error:] + 242

8  Rage Masters                  0x000d4046 0xd2000 + 8262

Thread 1:

0  libsystem_kernel.dylib        0x32803d98 __workq_kernreturn + 8

1  libsystem_c.dylib            0x3a987cf6 _pthread_workq_return + 14

2  libsystem_c.dylib            0x3a987a12 _pthread_wqthread + 362

3  libsystem_c.dylib            0x3a9878a0 start_wqthread + 4

// 5: 线程状态

Thread 0 crashed with ARM Thread State (32-bit):

r0: 0x00000000    r1: 0x00000000      r2: 0x00000001      r3: 0x39529fc8

r4: 0xffffffff    r5: 0x2fd7d301      r6: 0x2fd7d300      r7: 0x2fd7d9d0

r8: 0x2fd7d330    r9: 0x3adbf8a8    r10: 0x2fd7d308    r11: 0x00000032

ip: 0x00000025    sp: 0x2fd7d2ec      lr: 0x001bdb25      pc: 0x30301838

cpsr: 0x00000010

// 6: 二进制映像

Binary Images:

0xd2000 -    0xd7fff +Rage Masters armv7  /var/mobile/Applications/A5635B22-F5EF-4CEB-94B6-FE158D885014/Rage Masters.app/Rage Masters

0x2fe41000 - 0x2fe61fff  dyld armv7  /usr/lib/dyld

0x327f2000 - 0x32808fff  libsystem_kernel.dylib armv7  /usr/lib/system/libsystem_kernel.dylib

0x328a8000 - 0x328bdfff  libresolv.9.dylib armv7  /usr/lib/libresolv.9.dylib

0x32a70000 - 0x32b35fff  CFNetwork armv7  /System/Library/Frameworks/CFNetwork.framework/CFNetwork

0x32b7a000 - 0x32cc3fff  libicucore.A.dylib armv7  /usr/lib/libicucore.A.dylib

0x32cc4000 - 0x32cc5fff  CoreSurface armv7  /System/Library/PrivateFrameworks/CoreSurface.framework/CoreSurface

0x32f65000 - 0x32f8afff  OpenCL armv7  /System/Library/PrivateFrameworks/OpenCL.framework/OpenCL

这报告看起来像天书。:) 我们分几部分来解读吧:

(1) 进程信息

第一部分是闪退进程的相关信息。

Incident Identifier是崩溃报告的唯一标识符。

CrashReporter Key 是与设备标识相对应的唯一键值。虽然它不是真正的设备标识符,但也是一个非常有用的情报:如果你看到100个崩溃日志的CrashReporter Key值都是相同的,或者只有少数几个不同的CrashReport值,说明这不是一个普遍的问题,只发生在一个或少数几个设备上。

Hardware Model 标识设备类型。 如果很多崩溃日志都是来自相同的设备类型,说明应用只在某特定类型的设备上有问题。上面的日志里,崩溃日志产生的设备是iPhone 4s。

Process 是应用名称。中括号里面的数字是闪退时应用的进程ID。

(2) 基本信息

这部分给出了一些基本信息,包括闪退发生的日期和时间,设备的iOS版本。如果有很多崩溃日志都来自iOS 6.0,说明问题只发生在iOS 6.0上。

(3) 异常

在这部分,你可以看到闪退发生时抛出的异常类型。还能看到异常编码和抛出异常的线程。根据崩溃报告类型的不同,在这部分你还能看到一些另外的信息。

(4) 线程回溯

这部分提供应用中所有线程的回溯日志。 回溯是闪退发生时所有活动帧清单。它包含闪退发生时调用函数的清单。看下面这行日志:

2    XYZLib    0x34648e88    0x83000 + 8740

它包括四列:

帧编号—— 此处是2。

二进制库的名称 ——此处是 XYZLib.

调用方法的地址 ——此处是 0x34648e88.

第四列分为两个子列,一个基本地址和一个偏移量。此处是0×83000 + 8740, 第一个数字指向文件,第二个数字指向文件中的代码行。

(5) 线程状态

这部分是闪退时寄存器中的值。一般不需要这部分的信息,因为回溯部分的信息已经足够让你找出问题所在。

(6) 二进制映像

这部分列出了闪退时已经加载的二进制文件。

符号化Symbolication

第一次看到崩溃日志上的回溯时,你或许会觉得它没什么意义。我们习惯使用方法名和行数,而非像这样的神秘位置:

6    Rage Masters    0x0001625c    0x2a000 + 3003

将这些十六进制地址转化成方法名称和行数的过程称之为符号化。

从Xcode的Organizer窗口获取崩溃日志后过几秒钟,崩溃日志将被自动符号化。上面那行被符号化后的版本如下 :

6    Rage Masters    0x0001625c    -[RMAppDelegate application:didFinishLaunchingWithOptions:] (RMAppDelegate.m:35)

Xcode符号化崩溃日志时,需要访问与App Store上对应的应用二进制文件以及生成二进制文件时产生的 .dSYM 文件。必需完全匹配才行。否则,日志将无法被完全符号化。

所以,保留每个分发给用户的编译版本非常重要。提交应用前进行归档时,Xcode将保存应用的二进制文件。可以在Xcode Organizer的Archives标签栏下找到所有已归档的应用文件。

在发现崩溃日志时,如果有相匹配的.dSYM文件和应用二进制文件,Xcode会自动对崩溃日志进行符号化。如果你换到别的电脑或创建新的账户,务必将所有二进制文件移动到正确的位置,使Xcode能找到它们。

注意: 你必需同时保留应用二进制文件和.dSYM文件才能将崩溃日志完整符号化。每次提交到iTunes Connect的构建都必需归档。

.dSYM文件和二进制文件是特定绑定于每一次构建和后续构建的,即使来自相同的源代码文件,每一次构建也与其他构建不同,不能相互替换。

如果你使用Build 和 Archive 命令,这些文件会自动放在适当位置。 如果不是使用Build 和 Archive命令,放在Spotlight能够搜索到的位置(比如Home目录)即可。


低内存闪退

被iOS因释放内存页终止的进程名称后面你会看到jettisoned 字样。如果看到它出现在你的应用名称后面,说明你的应用因使用太多内存而被终止了。

低内存崩溃日志看起来像这样:

Incident Identifier: 30E46451-53FD-4965-896A-457FC11AD05F

CrashReporter Key:  5a56599d836c4f867f6eec76afee451bf9ae5f31

OS Version:          iPhone OS 3.1.3 (7E18)

Date/Time:          2012-10-17 21:39:06.967 -0400

Free pages:        96

Wired pages:      10558

Purgeable pages:  0

Largest process:  Rage Masters

Processes

Name                UUID                    Count resident pages

Rage Masters    9320 (jettisoned) (active)

mediaserverd      255

dataaccessd      505

syslogd      71

apsd      171

securityd      243

notifyd    2027

CommCenter      189

SpringBoard    2158 (active)

accessoryd      91

configd      371

fairplayd      93

mDNSResponder      292

lockdownd    1204

launchd      72

常见的异常编码:

0x8badf00d: 读做 “ate bad food”! (把数字换成字母,是不是很像 :p)该编码表示应用是因为发生watchdog超时而被iOS终止的。  通常是应用花费太多时间而无法启动、终止或响应用系统事件。

0xbad22222: 该编码表示 VoIP 应用因为过于频繁重启而被终止。

0xdead10cc: 读做 “dead lock”!该代码表明应用因为在后台运行时占用系统资源,如通讯录数据库不释放而被终止 。

0xdeadfa11: 读做 “dead fall”! 该代码表示应用是被用户强制退出的。根据苹果文档, 强制退出发生在用户长按开关按钮直到出现 “滑动来关机”, 然后长按 Home按钮。强制退出将产生 包含0xdeadfa11 异常编码的崩溃日志, 因为大多数是强制退出是因为应用阻塞了界面。

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

崩溃日志:

Incident Identifier: 85833DBA-3DF7-43EE-AF80-4E5C51091F42

CrashReporter Key:  5a56599d836c4f867f6eec76afee451bf9ae5f31

Hardware Model:      iPhone4,1

Process:        Rage Masters [20067]

Path:            /var/mobile/Applications/B2121A89-3D1F-4E61-BB18-5511E1DC150F/Rage Masters.app/Rage Masters

Identifier:      Rage Masters

Version:        ??? (???)

Code Type:      ARM (Native)

Parent Process:  launchd [1]

Date/Time:      2012-11-03 13:37:31.148 -0400

OS Version:      iOS 6.0 (10A403)

Report Version:  104

Exception Type:  00000020

Exception Codes: 0x000000008badf00d

Highlighted Thread:  0

Application Specific Information:

Soheil-Azarpour.Rage-Masters failed to launch in time

Elapsed total CPU time (seconds): 8.030 (user 8.030, system 0.000), 20% CPU

Elapsed application CPU time (seconds): 3.840, 10% CPU

Thread 0 name:  Dispatch queue: com.apple.main-thread

Thread 0:

0  libsystem_kernel.dylib        0x327f2eb4 mach_msg_trap + 20

1  libsystem_kernel.dylib        0x327f3048 mach_msg + 36

2  CoreFoundation                0x36bd4040 __CFRunLoopServiceMachPort + 124

3  CoreFoundation                0x36bd2d9e __CFRunLoopRun + 878

4  CoreFoundation                0x36b45eb8 CFRunLoopRunSpecific + 352

5  CoreFoundation                0x36b45d44 CFRunLoopRunInMode + 100

6  CFNetwork                    0x32ac343e CFURLConnectionSendSynchronousRequest + 330

7  Foundation                    0x346e69ba +[NSURLConnection sendSynchronousRequest:returningResponse:error:] + 242

8  Rage Masters                  0x000ea1c4 -[RMAppDelegate application:didFinishLaunchingWithOptions:] (RMAppDelegate.m:36)

9  UIKit                        0x37f30ad4 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 248

10  UIKit                        0x37f3065e -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1186

11  UIKit                        0x37f28846 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 694

12  UIKit                        0x37ed0c3c -[UIApplication handleEvent:withNewEvent:] + 1000

13  UIKit                        0x37ed06d0 -[UIApplication sendEvent:] + 68

14  UIKit                        0x37ed011e _UIApplicationHandleEvent + 6150

15  GraphicsServices              0x370835a0 _PurpleEventCallback + 588

16  GraphicsServices              0x370831ce PurpleEventCallback + 30

17  CoreFoundation                0x36bd4170 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 32

18  CoreFoundation                0x36bd4112 __CFRunLoopDoSource1 + 134

19  CoreFoundation                0x36bd2f94 __CFRunLoopRun + 1380

20  CoreFoundation                0x36b45eb8 CFRunLoopRunSpecific + 352

21  CoreFoundation                0x36b45d44 CFRunLoopRunInMode + 100

22  UIKit                        0x37f27480 -[UIApplication _run] + 664

23  UIKit                        0x37f242fc UIApplicationMain + 1116

24  Rage Masters                  0x000ea004 main (main.m:16)

25  libdyld.dylib                0x3b630b1c start + 0

发现问题了吗? 异常编码是0x000000008badf00d,还有后面的报告:

Application Specific Information:

Soheil-Azarpour.Rage-Masters failed to launch in time

Elapsed total CPU time (seconds): 8.030 (user 8.030, system 0.000), 20% CPU

Elapsed application CPU time (seconds): 3.840, 10% CPU

这说明应用在启动时就闪退了,iOS的watchdog机制终止了应用。帅! 找到问题了,但是为什会发生这样的事呢?

接着往下看日志。 从下向上读回溯日志。最底下的帧 (frame 25: libdyld.dylib)是最先调用的,然后是帧24, Rage Masters, main (main.m:16) ,依此类推。

跟应用源代码相关的帧是最重要的。忽略掉系统库和框架。下一个与代码相关的帧是:

8    Rage Masters    0x0009f244 -[RMAppDelegate application:didFinishLaunchingWithOptions:] (RMAppDelegate.m:35)

应用在执行RMAppDelegate (RMAppDelegate.m:35)类application:didFinishLaunchingWithOptions: 方法第35 行代码时闪退。打开Xcode看看那行代码:

NSData *directoryData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

就是它了! 同步调用web服务?! 在主线程上?! 在 application:didFinishLaunchingWithOptions: 方法上?!! 

这个调用必需异步进行,甚至更理想的情况是,在application:didFinishLaunchingWithOptions:返回YES之后的其他部分再执行Web服务。


显示这样的错误信息:NSGenericException ‘Collection was mutated while being enumerated”

”Collection was mutated while being enumerated”,意思是,一个对象(一般是NSArray什么的)在被访问的时候,这个对象发生了变化,导致程序挂掉了。在我的程序里,这个对象就是存储声音数据的东西,暂且叫它data。第1个线程会源源不断的向data里写入新数据,并将旧数据删掉。而第2个线程,则会定时读取data的内容并做处理。因为这两个线程每次操作data的时间都比较短,所以它们同时操作的情况不是很常见,所以一般程序也能坚持个几分钟。然而它们一旦同时对data进行操作/访问,程序就挂了。

解决方法也很简单,objective-c里有一个语法,专门处理这样的事:@synchronized(参数){代码块}

当两个@synchronized代码块的参数相同的时候,这两个代码块是不能同时操作的。对于参数,我们经常使用self来做参数。例如:

线程1:

@synchronized(self){

//写data

}

线程2:

@synchronized(self){

//读data

}

当线程1在写data时,线程2只能等着。这样就避免了同时多线程同时读/写global数据块会出现的闪退问题。

你可能感兴趣的:(如何查看iOS已上架APP的崩溃情况以及定位crash代码行)