Demystifying iOS Application Crash Logs

This is a blog post by Soheil Moayedi Azarpour, an independent iOS developer. You can also find him on Google+. Have you ever had the following experience as an app developer? Before you submit your app, you perform a lot of testing to make sure your app runs flawlessly. It works fine on your device, […] By Soheil Azarpour.

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 6 of this article. Click here to view the first page.

Scenario 1: Bad Code for Breakfast

From a user email: “Man, your app is a piece of junk! I downloaded it on my iPod Touch, iPhone and my son’s iPod Touch. On all devices, it crashed before running on the first try…”

Another email says, “I downloaded your app and it crashed. Very unhappy…”

Another email is more specific: “I can’t get your app to run. I downloaded it on all of my devices and on my wife’s. On all of them, it crashed on the first launch…”

OK, don’t take this lying down! Do any of these comments give you a hint? Take a look at the crash log:

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

Did you find the problem? The exception code is 0x000000008badf00d, and right after that, the report says:

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

This means that the app failed to launch in time, and the iOS watchdog terminated the app. Cool! You found the reason, but why (and more importantly, where) is it happening?

Look further down in the log. The convention is to read the backtrace log from the bottom up. The lowest frame (frame 25: libdyld.dylib) is the first call, then frame 24, Rage Masters, main (main.m:16) is called from there, and so on.

You are interested in frames that are related to your app’s code. So ignore system libraries and frameworks. The next line relevant to your code is:

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

The app failed in application:didFinishLaunchingWithOptions:, on line 35 in RMAppDelegate (RMAppDelegate.m:35). Open Xcode and take a look at that line:

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

Yep, there it is! A synchronous call to a web service?! On the main thread?! In application:didFinishLaunchingWithOptions:?!! Who wrote this code?!

Network calls on the main thread makes kittens sad.

Network calls on the main thread makes kittens sad.

Network calls on the main thread makes kittens sad.

Anyway, it’s your job to fix it. This call should be asynchronous and, even better, executed from another part of the application, after application:didFinishLaunchingWithOptions: has returned YES.

It might require more extensive changes to move the call elsewhere. So for the moment, just take care of the code so that it doesn’t crash. You can always go back and implement a better design later. Replace the line of offending code from above (and the three lines following it) with an asynchronous version:

[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];
         }];

Scenario 2: Button FUBAR

A user writes: “I can’t bookmark a rage master as my favorite. When I try to, the app crashes…”

Another user says, “Bookmarking doesn’t work… I go to detail info, tap on bookmark button and BOOM!”

The above complaints don’t say much, and there could be any number of causes for the issue they’ve identified. Take a look at the crash log:

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

The exception code is a SIGABRT. Usually, a SIGABRT exception is raised when an object receives an unimplemented message. Or to put it in simpler terms, there’s a call for a nonexistent method on an object.

Usually this won’t happen, since if you call method “foo” on object “bar”, the compiler will throw an error if the method “foo” doesn’t exist. But when you indirectly call a method using a selector, the compiler might not be able to determine whether or not the method exists on the object.

Back to the crash log. It indicates that the crashed thread is 0. This means that you’re probably looking at a situation where a method was called on an object on the main thread, where the object did not implement the method.

If you continue reading the backtrace log, you see that the only call related to your code is frame 22, main.m:16. That doesn’t help much. :[

Keep going up the framework calls, and there it is:

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

That isn’t your code. But at least it confirms that there was a call to an unimplemented method on an object.

Go to RMDetailViewController.m, since that’s where the bookmark button is implemented. Find the code that bookmarks the rage master:

-(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];
}

That looks OK, so check the storyboard (XIB file) and make sure that the button is hooked up correctly.

There it is! In MainStoryboard.storyboard, the button refers to bookmarkButtonPressed: instead of bookmarkButtonPressed (note the final colon indicating that the method expects a parameter). To fix this, replace the signature of the method above with this:

-(IBAction)bookmarkButtonPressed:(id)sender {
    // Remain unchanged...
}

Of course, you could also simply remove the incorrect connection in the XIB file and reconnect to the method, so that the method signature is correct in the XIB file. Either way works.

And that’s another crash fixed. You’re getting pretty good at this. :]

Contributors

Over 300 content creators. Join our team.