Contents

Identifying the cause of common crashes

Find patterns in crash reports that identify common problems, and investigate the issue based on the pattern.

Overview

You can identify the causes for many app crashes by looking for specific patterns in the crash report and taking specific diagnostic actions based on what the pattern shows. To recognize patterns, you consult two sections available in every crash report:

  • The exception code in the Exception Information section identifies the specific way the app crashed.

  • The backtraces show what code the thread was executing at the time of the crash.

[Image]

Some types of common crashes have a Diagnostic Messages section or a Last Exception Backtrace in the Backtraces section, which further describe the issue. These sections aren’t present in all crash reports. Examining the fields in a crash report describes each section and field in detail.

Compare the examples provided in this article to a crash report you’re investigating. Once you find a match, proceed to the more detailed article about that type of crash.

Determining whether your crash report contains a pattern for a common issue is the first step in diagnosing a problem. In some cases, the suggested diagnostic actions won’t identify the cause of the issue, requiring a more thorough analysis of the entire crash report. Analyzing a crash report describes how to perform a detailed analysis of a crash report.

Determine whether the crash is a Swift runtime error

Swift uses memory safety techniques to catch programming errors early. If the Swift runtime encounters a programming error, the runtime catches the error and intentionally crashes the app. These crashes have an identifiable pattern in the crash report. On ARM processors, the exception info in the crash report looks like:

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
...
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5

On Intel processors (including apps for macOS, Mac Catalyst, and the simulators for iOS, iPadOS, tvOS, and watchOS), the exception info in the crash report looks like:

Exception Type:        EXC_BAD_INSTRUCTION (SIGILL)
...
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Illegal instruction: 4
Termination Reason:    Namespace SIGNAL, Code 0x4

Additionally, the crash report shows the thread that encountered the error, with frame 0 in the backtrace identifying the specific line of code in your app containing the error, such as:

Thread 0 Crashed:
0   MyCoolApp                         0x0000000100a71a88 @objc ViewController.viewDidLoad() (in MyCoolApp) (ViewController.swift:18)

Addressing crashes from Swift runtime errors describes how to resolve this type of crash.

Determine whether the crash is an Objective-C concurrent property access error

The Objective-C runtime can detect when multiple threads concurrently write values to the same strong property; or when a thread reads a value from a strong property while another thread writes a value to the property. When the Objective-C runtime detects this situation, it catches the error and intentionally crashes the app. In most cases, the exception info in the crash report looks like this:

Exception Type:    EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x400000000000bad0 -> 0x000000000000bad0 (possible pointer authentication failure)

If the crash occurs in a 32-bit process on watchOS, the exception info in the crash report looks like this:

Exception Type:    EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000bad0

To resolve this type of crash, restructure your code so that different threads don’t concurrently read and write the property’s value. Alternatively, add the atomic keyword to the property declaration and ensure that all threads access the value through the property accessors:

@interface MyController : NSObject { }

@property (atomic, strong) MyAppService *service;

- (void)connectToService;
- (MyServiceResult *)updateServiceStatus;

@end

@implementation MyController

- (void)connectToService {
    dispatch_async(aQueue, ^{
        self.service = [[MyAppService alloc] init];
        [self.service connect];
    });
}

- (MyServiceResult *)updateServiceStatus {
    return self.service.status;
}

@end

For information on using Thread Sanitizer to detect concurrent access to memory locations, see Diagnosing memory, thread, and crash issues early.

Look for signs of a language exception

Apple’s system frameworks throw language exceptions when they encounter certain types of programming errors at runtime, such as accessing an array with an index that’s out-of-bounds. To determine whether a crash is due to a language exception, first confirm that the crash report contains this pattern:

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

A crash due to a language exception also has a Last Exception Backtrace in the crash report:

Last Exception Backtrace:
0   CoreFoundation                    0x19aae2a48 __exceptionPreprocess + 220
1   libobjc.A.dylib                   0x19a809fa4 objc_exception_throw + 55

If your crash report contains these patterns, see Addressing language exception crashes for how to address the crash.

Check for watchdog information

The operating system employs a watchdog to monitor app responsiveness. If an app is unresponsive, the watchdog terminates it, which creates a crash report with the 0x8badf00d code in the Termination Reason:

Exception Type:  EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d

In the crash report for an unresponsive app, the Termination Description contains information from the watchdog about how the app spent its time. For example:

Termination Description: SPRINGBOARD, 
    scene-create watchdog transgression: application<com.example.MyCoolApp>:667
    exhausted real (wall clock) time allowance of 19.97 seconds 
    | ProcessVisibility: Foreground 
    | ProcessState: Running 
    | WatchdogEvent: scene-create 
    | WatchdogVisibility: Foreground 
    | WatchdogCPUStatistics: ( 
    |  "Elapsed total CPU time (seconds): 15.290 (user 15.290, system 0.000), 28% CPU", 
    |  "Elapsed application CPU time (seconds): 0.367, 1% CPU" 
    | )

See Addressing watchdog terminations to diagnose why your app is unresponsive.

Determine whether the crash report contains signs of a zombie

Zombie objects are objects that are messaged by the Objective-C runtime after they’re deallocated from memory and no longer exist. Messaging a deallocated object can cause a crash in the objc_msgSend, objc_retain, or objc_release functions of the Objective-C runtime, such as this example with objc_msgSend:

Thread 0 Crashed:
0   libobjc.A.dylib                   0x00000001a186d190 objc_msgSend + 16
1   Foundation                        0x00000001a1f31238 __NSThreadPerformPerform + 232
2   CoreFoundation                    0x00000001a1ac67e0 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24

A different pattern that also indicates a zombie object is the presence of a Last Exception Backtrace with a stack frame containing the doesNotRecognizeSelector(_:) method:

Last Exception Backtrace:
0   CoreFoundation                    0x1bf596a48 __exceptionPreprocess + 220
1   libobjc.A.dylib                   0x1bf2bdfa4 objc_exception_throw + 55
2   CoreFoundation                    0x1bf49a5a8 -[NSObject+ 193960 (NSObject) doesNotRecognizeSelector:] + 139

If your crash report shows your app has a zombie, see Investigating crashes for zombie objects.

Determine whether there’s a memory access issue

When your app uses memory in an unexpected way, you’ll receive a crash report about a memory access issue. These types of crash reports have a EXC_BAD_ACCESS exception type, plus additional information in the VM Region Info field. For example:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
VM Region Info: 0 is not in any region.  Bytes before following region: 4307009536

      REGION TYPE                      START - END             [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->
      __TEXT                 0000000100b7c000-0000000100b84000 [   32K] r-x/r-x SM=COW  ...pp/MyGreatApp

Investigating memory access crashes contains information on the different types of memory access issues and how to investigate them.

Determine whether a framework is missing

If an app crashes because it’s missing a required framework, the crash report contains the EXC_CRASH (SIGABRT) exception code. You’ll also find a Termination Description in the crash report, identifying the specific framework that the dynamic linker, dyld, couldn’t locate. Here’s an example, with extra line breaks included for readability:

Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Description: DYLD, dependent dylib '@rpath/MyFramework.framework/MyFramework'
    not found for '<path>/MyCoolApp.app/MyCoolApp', tried but didn't find: 
    '/usr/lib/swift/MyFramework.framework/MyFramework' 
    '<path>/MyCoolApp.app/Frameworks/MyFramework.framework/MyFramework' 
    '@rpath/MyFramework.framework/MyFramework' 
    '/System/Library/Frameworks/MyFramework.framework/MyFramework'

Addressing missing framework crashes discusses how to resolve this issue.

Topics

Runtime errors

System terminations

Memory access errors

App configuration errors

See Also

Crash reports