美文网首页iOS Developer
崩溃日志详解下

崩溃日志详解下

作者: 中二修行者 | 来源:发表于2017-02-13 10:50 被阅读271次

    异常编码

    在研究真实闪退场景之前,还有一点需要重点介绍一下:就是那些有趣的异常编码 。

    你可以在报告的异常部分——前面代码的第3部分找到异常编码。有些编码比较常见。

    通常,异常编码以一些文字开头,紧接着是一个或多个十六进制值,此数值正是说明闪退根本性质的所在。  从这些编码中,可以区分出闪退是因为程序错误、非法内存访问或者是其他原因。

    下面是一些常见的异常编码:

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

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

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

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

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

    大展身手的时候到了!

    好了! 你已经学习了所有分析崩溃日志和修复错误的基础知识!

    假设你刚进入Rage-O-Rage有限公司工作。该公司有一个在App Store上热销的应用,叫 Rage Masters。

    你的老板安迪要你帮忙解决几个用户经常抱怨闪退问题。你的任务就是研究这些闪退,符号化用户提供的崩溃日志,查找问题所在,并修复之。

    你可以从  这里下载应用的源代码。

    注意: 如果你想自己重新生成崩溃报告,请遵照以下指引:

    下载源码然后在Xcode中打开工程文件。

    使用正确的provisioning profile连接到iOS设备。

    从Xcode工具栏上选择iOS设备——不是模拟器作为target,然后构建应用。

    当你在设备上到默认页面(应用的全屏图片)时,立即在Xcode上点击停止按钮。

    关闭 Xcode。

    在设备上直接打开应用。

    测试场景,完成后连接设备到电脑上,通过Xcode获取崩溃日志。

    场景 1: 糟糕的代码

    一封来自用户的邮件: “大哥,你的应用就是一坨屎! 我将其下载到我自己的iPod Touch和iPhone上,还下载到我儿子的iPod Touch上。在所有的设备上,都是还没打开就闪退了……”

    别一封来自用户的邮件说, “我下载了你们的应用,一打开就闪退。真悲催…”

    另一封邮件说得更明确:”你们的应用不能运行。我把它下载到我和妻子的设备上。所有设备都是 一打开就闪退了…”

    好吧,别灰心! 这些意见藏着什么玄机呢?让我们看看崩溃日志吧:

    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: 方法上?!! 谁写的代码呀?!

    Network calls on the main thread makes kittens sad.

    Network calls on the main thread makes kittens sad.

    不管如何,问题得你来修复了。这个调用必需异步进行,甚至更理想的情况是,在 application:didFinishLaunchingWithOptions:返回YES之后的其他部分再执行Web服务。

    在其他地方调用可能需要比较多的修改。当下,我们只要使应用不闪退就行。可以在日后再实现更好的设计。 将上面那行讨厌的代码(及其下面的三行代码)换成下面这个异步的版本吧:

    [NSURLConnection sendAsynchronousRequest:request

    queue:[NSOperationQueue mainQueue]

    completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)

    {

    NSURL *cacheDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSUserDirectory inDomains:NSCachesDirectory] lastObject];

    NSURL *filePath = [NSURL URLWithString:kDirectoryFile relativeToURL:cacheDirectory];

    [data writeToFile:[filePath absoluteString] atomically:YES];

    }];

    场景 2: 无法响应事件的按钮

    一名用户说: “我不能将某个rage master添加到书签里面。我想添加的时候应用就闪退…”

    用一名用户说 :”书签不能用 … 在详细页面上,点击书签按钮,应用就闪退了!”

    上面的抱怨说得不是很清楚,引起问题的原因肯定有多样。看看崩溃日志:

    Incident Identifier: 3AAA63CC-3088-41CC-84D9-82FE03F9F354

    CrashReporter Key:  5a56599d836c4f867f6eec76afee451bf9ae5f31

    Hardware Model:      iPhone4,1

    Process:        Rage Masters [20090]

    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:39:00.081 -0400

    OS Version:      iOS 6.0 (10A403)

    Report Version:  104

    Exception Type:  EXC_CRASH (SIGABRT)

    Exception Codes: 0x0000000000000000, 0x0000000000000000

    Crashed Thread:  0

    Last Exception Backtrace:

    0  CoreFoundation                    0x36bff29e __exceptionPreprocess + 158

    1  libobjc.A.dylib                  0x34f0f97a objc_exception_throw + 26

    2  CoreFoundation                    0x36c02e02 -[NSObject(NSObject) doesNotRecognizeSelector:] + 166

    3  CoreFoundation                    0x36c0152c ___forwarding___ + 388

    4  CoreFoundation                    0x36b58f64 _CF_forwarding_prep_0 + 20

    5  UIKit                            0x37fbb0a8 -[UIApplication sendAction:to:from:forEvent:] + 68

    6  UIKit                            0x37fbb05a -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 26

    7  UIKit                            0x37fbb038 -[UIControl sendAction:to:forEvent:] + 40

    8  UIKit                            0x37fba8ee -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 498

    9  UIKit                            0x37fbade4 -[UIControl touchesEnded:withEvent:] + 484

    10  UIKit                            0x37ee35f4 -[UIWindow _sendTouchesForEvent:] + 520

    11  UIKit                            0x37ed0804 -[UIApplication sendEvent:] + 376

    12  UIKit                            0x37ed011e _UIApplicationHandleEvent + 6150

    13  GraphicsServices                  0x3708359e _PurpleEventCallback + 586

    14  GraphicsServices                  0x370831ce PurpleEventCallback + 30

    15  CoreFoundation                    0x36bd416e __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 30

    16  CoreFoundation                    0x36bd4112 __CFRunLoopDoSource1 + 134

    17  CoreFoundation                    0x36bd2f94 __CFRunLoopRun + 1380

    18  CoreFoundation                    0x36b45eb8 CFRunLoopRunSpecific + 352

    19  CoreFoundation                    0x36b45d44 CFRunLoopRunInMode + 100

    20  GraphicsServices                  0x370822e6 GSEventRunModal + 70

    21  UIKit                            0x37f242fc UIApplicationMain + 1116

    22  Rage Masters                      0x000ca004 main (main.m:16)

    23  libdyld.dylib                    0x3b630b1c start + 0

    异常代码是SIGABRT。通常,  SIGABRT 异常是由于某个对象接收到未实现的消息引起的。 或者,用简单的话说,在某个对象上调用了不存在的方法。

    这种情况一般不会发生,因为A对象调用了B方法,如果B方法不存在,编译器会报错。但是,如果你是使用selector间接调用方法的,编译器则无法检测对象是否存在该方法了。

    回到崩溃日志。它指出闪退发生在编号为0的线程上。 这意味着很可能是在主线程上调用了某个对象没有实现的方法。

    如果你接着阅读回溯日志,会发现跟你的代码相关的只有帧22, main.m:16. 这没有多大帮助。 :[

    继续向上查看框架调用,出现这个:

    2    CoreFoundation    0x36c02e02 -[NSObject(NSObject) doesNotRecognizeSelector:] + 166

    这不是你自己写的代码。但至少它确认了是对象调用了一个没有实现的方法。

    回到 RMDetailViewController.m文件, 因为那是书签按钮实现动作的地方。 找到书签功能代码:

    -(IBAction)bookmarkButtonPressed {

    self.master.isBookmarked = !self.master.isBookmarked;

    // Update shared bookmarks

    if (self.master.isBookmarked)

    [[RMBookmarks sharedBookmarks] bookmarkMaster:self.master];

    else

    [[RMBookmarks sharedBookmarks] unbookmarkMaster:self.master];

    // Update UI

    [self updateBookmarkImage];

    }

    看起来没什么问题,再检查一下storyboard (XIB文件) ,确认按钮连接的正确性。

    就是它了! 在  MainStoryboard.storyboard,按钮连接的是 bookmarkButtonPressed: 而不是bookmarkButtonPressed (注意后面的分号说明方法有一个参数)。 只要将上面的方法签名修改成这样就能修复问题了:

    -(IBAction)bookmarkButtonPressed:(id)sender {

    // Remain unchanged..

    }

    当然,你也可以简单地在XIB文件上删除错误的连接,然后重新连接方法,使XIB文件连接到正确的方法上。两者方法都行。

    又处理了一个闪退问题,好样的。:]

    场景 3: 表格上的Bug

    另一用户抱怨道, “在书签视图上无法删除书签…” 还有另一用户抱怨同样的问题, “当我试图删除书签时,应用闪退…”

    这些邮件没什么作用,还是看看崩溃日志!

    Incident Identifier: 5B62D681-D8FE-41FE-8D52-AB7E6D6B2AC7

    CrashReporter Key:  5a56599d836c4f867f6eec76afee451bf9ae5f31

    Hardware Model:      iPhone4,1

    Process:        Rage Masters [20088]

    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:38:45.762 -0400

    OS Version:      iOS 6.0 (10A403)

    Report Version:  104

    Exception Type:  EXC_CRASH (SIGABRT)

    Exception Codes: 0x0000000000000000, 0x0000000000000000

    Crashed Thread:  0

    Last Exception Backtrace:

    0  CoreFoundation                    0x36bff29e __exceptionPreprocess + 158

    1  libobjc.A.dylib                  0x34f0f97a objc_exception_throw + 26

    2  CoreFoundation                    0x36bff158 +[NSException raise:format:arguments:] + 96

    3  Foundation                        0x346812aa -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 86

    4  UIKit                            0x37f04b7e -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] + 7690

    5  UIKit                            0x3803a4a2 -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] + 22

    6  Rage Masters                      0x000fd9ca -[RMBookmarksViewController tableView:commitEditingStyle:forRowAtIndexPath:] (RMBookmarksViewController.m:68)

    7  UIKit                            0x3809a5d4 -[UITableView(UITableViewInternal) animateDeletionOfRowWithCell:] + 80

    8  UIKit                            0x37fbb0a8 -[UIApplication sendAction:to:from:forEvent:] + 68

    9  UIKit                            0x37fbb05a -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 26

    10  UIKit                            0x37fbb038 -[UIControl sendAction:to:forEvent:] + 40

    11  UIKit                            0x37fba8ee -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 498

    12  UIKit                            0x37fbb0a8 -[UIApplication sendAction:to:from:forEvent:] + 68

    13  UIKit                            0x37fbb05a -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 26

    14  UIKit                            0x37fbb038 -[UIControl sendAction:to:forEvent:] + 40

    15  UIKit                            0x37fba8ee -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 498

    16  UIKit                            0x37fbade4 -[UIControl touchesEnded:withEvent:] + 484

    17  UIKit                            0x37ee35f4 -[UIWindow _sendTouchesForEvent:] + 520

    18  UIKit                            0x37ed0804 -[UIApplication sendEvent:] + 376

    19  UIKit                            0x37ed011e _UIApplicationHandleEvent + 6150

    20  GraphicsServices                  0x3708359e _PurpleEventCallback + 586

    21  GraphicsServices                  0x370831ce PurpleEventCallback + 30

    22  CoreFoundation                    0x36bd416e __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 30

    23  CoreFoundation                    0x36bd4112 __CFRunLoopDoSource1 + 134

    24  CoreFoundation                    0x36bd2f94 __CFRunLoopRun + 1380

    25  CoreFoundation                    0x36b45eb8 CFRunLoopRunSpecific + 352

    26  CoreFoundation                    0x36b45d44 CFRunLoopRunInMode + 100

    27  GraphicsServices                  0x370822e6 GSEventRunModal + 70

    28  UIKit                            0x37f242fc UIApplicationMain + 1116

    29  Rage Masters                      0x000fb004 main (main.m:16)

    30  libdyld.dylib                    0x3b630b1c start + 0

    这看起来跟前面那个崩溃日志很像。是另一个SIGABRT 异常。 你可能想知道是否是相同的问题:发送信息到一个没有实现相应方法的对象?

    让我们从回溯日志看看哪些方法被调用了。从底部开始,你的源代码最后被调用的是帧 6:

    6    Rage Masters    0x00088c66 -[RMBookmarksViewController tableView:commitEditingStyle:forRowAtIndexPath:] (RMBookmarksViewController.m:68)

    这是UITableViewDataSource 的一个方法. 呵呵?! 毫无疑问苹果已经实现了该方法 —— 你可以重载它, 但不像是还没有实现。而且,这是个可选的委派方法。 所以问题不是调用了一个没有实现的方法。

    再看看上面的几个帧:

    3    Foundation    0x346812aa -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 86

    4    UIKit        0x37f04b7e -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] + 7690

    5    UIKit        0x3803a4a2 -[UITableView deleteRowsAtIndexPaths:withRowAnimation:] + 22

    帧 5, UITableView调用了它自己的另一个方法  deleteRowsAtIndexPaths:withRowAnimation: 然后是看起来像苹果内部方法的 _endCellAnimationsWithContext: 被调用。然后Foundation framework发生异常 handleFailureInMethod:object:file:lineNumber:description:.

    这些分析结合用户的抱怨,看起来是你在处理UITableView删除行过程中有Bug。回到Xcode。你知道看哪里吗 ? 能从崩溃日志中判断出来? 就是 RMBookmarksViewController.m文件的第68行:

    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

    }

    发现问题了吗? 给你点时间,仔细看一下。

    找到了吧! 数据源呢? 代码在表格视图上删除了一行,但并没有修改背后的数据源。把上面的代码替换成下面的就能修复问题了:

    -(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    RMMaster *masterToDelete = [bookmarks objectAtIndex:indexPath.row];

    [bookmarks removeObject:masterToDelete];

    [[RMBookmarks sharedBookmarks] unbookmarkMaster:masterToDelete];

    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

    }

    搞定了!走起,讨厌的 bug!!

    场景 4: 吃棒棒糖时闪退!

    用户邮件说, “当rage master吃棒棒糖时应用就闪退…” 另一用户说, “我让rage master 吃棒棒糖,没几次应用就闪退了!”

    崩溃日志如下:

    Incident Identifier: 081E58F5-95A8-404D-947B-5E104B6BC1B1

    CrashReporter Key:  5a56599d836c4f867f6eec76afee451bf9ae5f31

    Hardware Model:      iPhone4,1

    OS Version:          iPhone OS 6.0 (10A403)

    Kernel Version:      Darwin Kernel Version 13.0.0: Sun Aug 19 00:28:05 PDT 2012; root:xnu-2107.2.33~4/RELEASE_ARM_S5L8940X

    Date:                2012-11-03 13:39:59 -0400

    Time since snapshot: 4353 ms

    Free pages:        968

    Active pages:      7778

    Inactive pages:    4005

    Throttled pages:  92319

    Purgeable pages:  0

    Wired pages:      23347

    Largest process:  Rage Masters

    Processes

    Name                                          rpages      recent_max      [reason]          (state)

    lsd <6a9f5b5f36b23fc78f87b6d8f1f49a9d>          331              331        [vm]        (daemon) (idle)

    afcd          141              141        [vm]        (daemon) (idle)

    itunesstored <4e0cd9f873de3435b4119c48b2d6d13d>        1761            1761        [vm]        (daemon) (idle)

    softwareupdatese <2bc4b5ae016431c98d3b34f81027d0ae>          311              311        [vm]        (daemon) (idle)

    Amazon <4600481f07ec3e59a925319b7f67ba14>        2951            2951        [vm]        (suspended)

    accountsd          519              519        [vm]        (daemon) (idle)

    coresymbolicatio          126              126        [vm]        (daemon) (idle)

    Skype <504cf2fe60cb3cdea8273e74df09836b>        3187            3187        [vm]        (background)

    MobileMail        14927            14927        [vm]        (continuous)

    MobileSMS <46778de076363d67aeea207464cfc581>        2134            2134        [vm]        (background)

    MobilePhone <3fca241f2a193d0fb8264218d296ea41>        2689            2689        [vm]        (continuous)

    librariand          317              317        [vm]        (daemon)

    kbd <3e7136ddcefc3d77a01499db593466cd>          616              616        [vm]        (daemon)

    tccd          224              224        [vm]        (daemon)

    Rage Masters <90b45d6281e934209c5b06cf7dc4d492>        28591            28591        [vm]        (frontmost) (resume)

    ptpd <04a56fce67053c57a7979aeea8e5a7ea>          879              879                      (daemon)

    iaptransportd          230              230                      (daemon)

    locationd <892cd1c9ffa43c99a82dba197be5f09e>        1641            1641                      (daemon)

    syslogd          237              237                      (daemon)

    mediaserverd <80657170daca32c9b8f3a6b1faac43a2>        4869            4869                      (daemon)

    dataaccessd <2a3f6a518f3f3646bf35eddd36f25005>        1786            1786                      (daemon)

    aosnotifyd          549              549                      (daemon)

    wifid <9472b090746237998cdbb9b34f090d0c>          455              455                      (daemon)

    SpringBoard <27372aae101f3bbc87804edc10314af3>        18749            18749

    backboardd <5037235f295b33eda98eb5c72c098858>        5801            5801                      (daemon)

    UserEventAgent <6edfd8d8dba23187b05772dcdfc94f90>          601              601                      (daemon)

    mediaremoted <4ff39c50c684302492e396ace813cb25>          293              293                      (daemon)

    pasteboardd <8a4279b78e4a321f84a076a711dc1c51>          176              176                      (daemon)

    springboardservi            0                0                      (daemon)

    syslog_relay <45e9844605d737a08368b5215bb54426>            0                0                      (daemon)

    DTMobileIS <23303ca402aa3705870b01a9047854ea>            0                0                      (daemon)

    notification_pro <845b7beebc8538ca9ceef731031983b7>          169              169                      (daemon)

    syslog_relay <45e9844605d737a08368b5215bb54426>            0                0                      (daemon)

    ubd <74dc476d1785300e9fcda555fcb8d774>          976              976                      (daemon)

    twitterd <4b4946378a9c397d8250965d17055b8e>          730              730                      (daemon)

    configd <4245d73a9e96360399452cf6b8671844>          809              809                      (daemon)

    absinthed.N94 <7f4164c844fa340caa940b863c901aa9>          99              99                      (daemon)

    filecoordination          226              226                      (daemon)

    distnoted          137              137                      (daemon)

    apsd <94d8051dd5f5362f82d775bc279ae608>          373              373                      (daemon)

    networkd <0032f46009f53a6c80973fe153d1a588>          219              219                      (daemon)

    aggregated <8c3c991dc4153bc38aee1e841864d088>          112              112                      (daemon)

    BTServer          522              522                      (daemon)

    fairplayd.N94 <7bd896bd00783a48906090d05cf1c86a>          210              210                      (daemon)

    fseventsd <996cc4ca03793184aea8d781b55bce08>          384              384                      (daemon)

    imagent <1e68080947be352590ce96b7a1d07b2f>          586              586                      (daemon)

    mDNSResponder <3e557693f3073697a58da6d27a827d97>          295              295                      (daemon)

    lockdownd          389              389                      (daemon)

    powerd <2d2ffed5e69638aeba1b92ef124ed861>          174              174                      (daemon)

    CommCenter <1f425e1e897d32e8864fdd8eeaa803a8>        2212            2212                      (daemon)

    notifyd <51c0e03da8a93ac8a595442fcaac531f>          211              211                      (daemon)

    ReportCrash <8c32f231b2ed360bb151b2563bcaa363>          337              337                      (daemon)

    这日志跟我们前面见到的相差很多。

    这个一个来自iOS 6的低内存崩溃日志。正如我们前面所说的,低内存崩溃日志与其他类型的崩溃日志很不一样,它们不指向特定的文件和代码行。相反,它们画出了闪退时设备上的内存使用情况的图表。

    至少,头部还是跟其他崩溃日志很像的:  提供了 Incident Identifier, CrashReporter Key, Hardware Model, OS Version等信息。

    接下来部分是低内存崩溃日志特有的:

    Free pages 指可用内存页数。每页大小约是4KB, 上面的日志中,可用内存约为3,872 KB (或者说 3.9 MB)。

    Purgeable pages 是那部分可被清除或重用的内存。在上面的日志中,是0KB。

    Largest process是闪退时使用大部分内存的应用名称,在上面的日志中,正是你的应用!

    Processes显示了闪退时各进程列表,还包含内存使用量。包含进程名 (第一列), 进程唯一标识符(第二名), 进程使用的内存页数(第三列)。最后一列是每个应用的状态。通常,发生闪退的应用的状态是 frontmost。 这里是 Rage Masters, 使用28591 页 (or 114.364 MB) 内存——这内存太多了!

    通过,最大进程和frontmost状态的应用是相同的, 而且也是引起低内存闪退的应用进程。但是也可能看到最大进程和 frontmost状态应用不同的例子。比如,如果最大进程是SpringBoard, 忽略它 , 因为 SpringBoard 进程是显示主屏幕的应用,出现在你双击home按钮等情况,而且它是一直活动的。

    低内存发生时,iOS向活动的应用发出低内存警告并终止后台应用。如果前台应用仍然继续增长内存,iOS将终止它。

    为了查找低内存问题的原因,你必需使用Instruments剖析应用。如果你不知道怎么做,可以看一下我们 一篇关于这个方面的教程.。 :] 另外, 你也可以走捷径,响应低内存警告通知,以解决部分闪退问题。

    回到Xcode查看RMLollipopLicker.m文件。 这是实现吃棒棒糖的视图控制器。看看源代码:

    #import "RMLollipopLicker.h"

    #define COUNT 20

    @interface RMLollipopLicker ()

    @property (weak, nonatomic) IBOutlet UIProgressView *progressView;

    @property (weak, nonatomic) IBOutlet UILabel *label;

    @property (weak, nonatomic) IBOutlet UILabel *lickedTimeLabel;

    @end

    @implementation RMLollipopLicker {

    NSOperationQueue *queue;

    NSMutableArray *lollipops;

    }

    #pragma mark - Life cycle

    - (void)viewDidLoad {

    [super viewDidLoad];

    self.progressView.progress = 0.0;

    self.label.text = [NSString stringWithFormat:@"Tap on run and I'll lick a lollipop %d times!", COUNT];

    self.lickedTimeLabel.text = @"";

    lollipops = [[NSMutableArray alloc] init];

    queue = [[NSOperationQueue alloc] init];

    }

    - (void)lickLollipop {

    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"Lollipop" withExtension:@"plist"];

    NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:fileURL];

    NSString *lollipop = [dictionary objectForKey:@"Lollipop"];

    [lollipops addObject:lollipop];

    }

    #pragma mark - IBActions

    - (IBAction)doneButtonPressed:(id)sender {

    [self dismissViewControllerAnimated:YES completion:nil];

    }

    - (IBAction)runButtonPressed:(id)sender {

    [sender setEnabled:NO];

    [queue addOperationWithBlock:^{

    for (NSInteger i = 0 ; i = COUNT) {

    self.label.text = [NSString stringWithFormat:@"Tap on run and I'll lick a lollipop %d times!", COUNT];

    self.progressView.progress = 0.0;

    [sender setEnabled:YES];

    }

    }];

    }

    }];

    }

    @end

    当用户点击运行按钮, 应用开始一个背景线程,调用 lickLollipop 方法若干次,然后更新界面反映吃棒棒糖的数量。 lickLollipop 方法从属性列表文件(PLIST)文件读取一个长字符串,然后添加到数组上。这些数据并不重要, 能在不影响用户体验的前提下重新创建。

    利用每种能够清除和重建数据而不影响用户体验的情况是好习惯。这样能够方便地释放内存,减少低内存警告。

    那么,如何提高代码质量呢? 实现 didReceiveMemoryWarning 方法,像下面这样处理数据:

    -(void)didReceiveMemoryWarning {

    [lollipops removeAllObjects];

    [super didReceiveMemoryWarning];

    }

    搞定!

    下一步?

    万岁,你研究了4个闪退案例! 你的应用更完善了,并且学到了一些重要的调试技巧。

    你可以到 这里下载改进后的项目代码。

    相关文章

      网友评论

        本文标题:崩溃日志详解下

        本文链接:https://www.haomeiwen.com/subject/iwvzittx.html