EXC_BAD_ACCESS Crash that we can't get rid of

Hello to everyone!

We are getting this crash at 4% of our users and it occuries right at start of application, so the users can't open the app 😦

The problem is that we can't repeat this crash at our test devices, though we tried A LOT of them.

So the main question is - How to detect location of the issue if we can't repeat the crash at our test devices?

If you have ANY ideas how we can solve this issue, we would be very grateful!

Thanks in advance!

Crashed: Thread
EXC_BAD_ACCESS 0x0000000000000001
0  QuartzCore        CA::Layer::retain_parent(CA::Transaction*) const + 60
1  QuartzCore        CA::Layer::retain_parent(CA::Transaction*) const + 52
2  QuartzCore        CALayerGetSuperlayer + 56
3  UIKitCore         -[UIView(UIKitManual) superview] + 56
4  UIKitCore         -[UIView _updateSafeAreaInsets] + 64
5  UIKitCore         -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2836
6  QuartzCore        -[CALayer layoutSublayers] + 308
7  QuartzCore        CA::Layer::layout_if_needed(CA::Transaction*) + 548
8  QuartzCore        CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 144
9  QuartzCore        CA::Context::commit_transaction(CA::Transaction*, double, double*) + 500
10 QuartzCore        CA::Transaction::commit() + 684
11 QuartzCore        CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 96
12 CoreFoundation    __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36
13 CoreFoundation    __CFRunLoopDoObservers + 572
14 CoreFoundation    __CFRunLoopRun + 1052
15 CoreFoundation    CFRunLoopRunSpecific + 600
16 GraphicsServices  GSEventRunModal + 164
17 UIKitCore         -[UIApplication _run] + 1072
18 UIKitCore         UIApplicationMain + 168
19 Slowdive          (Missing)
20 libdyld.dylib     start + 4

com.apple.uikit.eventfetch-thread
0  libsystem_kernel.dylib   mach_msg_trap + 8
1  libsystem_kernel.dylib   mach_msg + 76
2  CoreFoundation           __CFRunLoopServiceMachPort + 372
3  CoreFoundation           __CFRunLoopRun + 1212
4  CoreFoundation           CFRunLoopRunSpecific + 600
5  Foundation               -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 232
6  Foundation               -[NSRunLoop(NSRunLoop) runUntilDate:] + 92
7  UIKitCore                -[UIEventFetcher threadMain] + 516
8  Foundation               __NSThread__start__ + 864
9  libsystem_pthread.dylib  _pthread_start + 320

Thread
0  libsystem_kernel.dylib      __semwait_signal + 8
1  libsystem_c.dylib           nanosleep + 216
2  libsystem_c.dylib           sleep + 48
3  YandexMobileMetricaCrashes  YMM__ksccd_init + 968
4  libsystem_pthread.dylib     _pthread_start + 320

KSCrash Exception Handler (Secondary)
0  libsystem_kernel.dylib      mach_msg_trap + 8
1  libsystem_kernel.dylib      mach_msg + 76
2  YandexMobileMetricaCrashes  YMM__kscm_machexception_getAPI + 1012
3  libsystem_pthread.dylib     _pthread_start + 320

KSCrash Exception Handler (Primary)
0  (Missing)  (Missing)

com.google.firebase.crashlytics.MachExceptionServer
0  libsystem_kernel.dylib   mach_msg_trap + 8
1  libsystem_kernel.dylib   mach_msg + 76
2  FirebaseCrashlytics      FIRCLSMachExceptionMaskForSignal + 1080
3  libsystem_pthread.dylib  _pthread_start + 320

com.apple.NSURLConnectionLoader
0  libsystem_kernel.dylib   mach_msg_trap + 8
1  libsystem_kernel.dylib   mach_msg + 76
2  CoreFoundation           __CFRunLoopServiceMachPort + 372
3  CoreFoundation           __CFRunLoopRun + 1212
4  CoreFoundation           CFRunLoopRunSpecific + 600
5  CFNetwork                (Missing)
6  Foundation               __NSThread__start__ + 864
7  libsystem_pthread.dylib  _pthread_start + 320

AVAudioSession Notify Thread
0  libsystem_kernel.dylib   mach_msg_trap + 8
1  libsystem_kernel.dylib   mach_msg + 76
2  CoreFoundation           __CFRunLoopServiceMachPort + 372
3  CoreFoundation           __CFRunLoopRun + 1212
4  CoreFoundation           CFRunLoopRunSpecific + 600
5  AudioSession             GenericRunLoopThread::Entry(void*) + 164
6  AudioSession             CAPThread::Entry(CAPThread*) + 92
7  libsystem_pthread.dylib  _pthread_start + 320

Thread
0  libsystem_kernel.dylib   __accept + 8
1  YandexMobileMetrica      ymm__wifi_network__free_unpacked + 20308
2  YandexMobileMetrica      ymm__event_data__free_unpacked + 110168
3  libdispatch.dylib        _dispatch_call_block_and_release + 32
4  libdispatch.dylib        _dispatch_client_callout + 20
5  libdispatch.dylib        _dispatch_lane_serial_drain + 620
6  libdispatch.dylib        _dispatch_lane_invoke + 404
7  libdispatch.dylib        _dispatch_workloop_worker_thread + 764
8  libsystem_pthread.dylib  _pthread_wqthread + 276

Thread
0  libsystem_pthread.dylib  start_wqthread + 0

Thread
0  libsystem_kernel.dylib   __workq_kernreturn + 8
1  libsystem_pthread.dylib  _pthread_wqthread + 352

Thread
0  libsystem_kernel.dylib   __workq_kernreturn + 8
1  libsystem_pthread.dylib  _pthread_wqthread + 352

Thread
0  libsystem_kernel.dylib   __workq_kernreturn + 8
1  libsystem_pthread.dylib  _pthread_wqthread + 352

Thread
0  libsystem_kernel.dylib   semaphore_timedwait_trap + 8
1  libdispatch.dylib        _dispatch_sema4_timedwait + 64
2  libdispatch.dylib        _dispatch_semaphore_wait_slow + 76
3  libdispatch.dylib        _dispatch_worker_thread + 304
4  libsystem_pthread.dylib  _pthread_start + 320

Thread
0  libsystem_kernel.dylib   semaphore_timedwait_trap + 8
1  libdispatch.dylib        _dispatch_sema4_timedwait + 64
2  libdispatch.dylib        _dispatch_semaphore_wait_slow + 76
3  libdispatch.dylib        _dispatch_worker_thread + 304
4  libsystem_pthread.dylib  _pthread_start + 320

Thread
0  libsystem_kernel.dylib   semaphore_timedwait_trap + 8
1  libdispatch.dylib        _dispatch_sema4_timedwait + 64
2  libdispatch.dylib        _dispatch_semaphore_wait_slow + 76
3  libdispatch.dylib        _dispatch_worker_thread + 304
4  libsystem_pthread.dylib  _pthread_start + 320

Thread
0  libsystem_kernel.dylib   semaphore_timedwait_trap + 8
1  libdispatch.dylib        _dispatch_sema4_timedwait + 64
2  libdispatch.dylib        _dispatch_semaphore_wait_slow + 76
3  libdispatch.dylib        _dispatch_worker_thread + 304
4  libsystem_pthread.dylib  _pthread_start + 320

Crashlogs like this are usually indicative of some form of memory corruption, specifically heap corruption (since all CALayers and UIViews are allocated on the heap).

While you may not be able to reproduce the issue on your test devices, Xcode does have some tools that you can use to try and spot memory errors. One that may be of particular use for you is Guard Malloc.

From our documentation:

Guard Malloc is a special version of the malloc library that replaces the standard library during debugging. Guard Malloc uses several techniques to try and crash your application at the specific point where a memory error occurs. For example, it places separate memory allocations on different virtual memory pages and then deletes the entire page when the memory is freed. Subsequent attempts to access the deallocated memory cause an immediate memory exception rather than a blind access into memory that might now hold other data. When the crash occurs, you can then go and inspect the point of failure in the debugger to identify the problem.

This option is available in Xcode in the "Run" tab under your scheme options, underneath "Diagnostics". While running with Guard Malloc, common memory errors will trigger an exception to occur instead of just clobbering memory only to cause problems/crashes later on. This will help you to narrow down the problematic area of your code.

Another option there that might be useful is Malloc Scribble. This will help you determine whether or not the crash here is happening because of a use-after-free error. When Malloc Scribble is enabled, all freed areas of memory will be populated with 0x55. This means if you can get it to crash, and the top of the crash report says something like:

EXC_BAD_ACCESS 0x5555555555555555

instead of what's in your crash report from the field: EXC_BAD_ACCESS 0x0000000000000001, then you know you have a use-after-free error.

Since this memory error is specifically involving UIKit views or CALayers, I would also make absolute sure that you're only accessing UIKit methods on the main thread. UIKit is not thread safe, which means if you end up mutating a view on a background thread, a crash just like this might happen in the next turn of the runloop (so your stacktrace won't help you find where it was mutated, necessarily).

There is in fact another Xcode tool that you can use to help with that as well. In the same "Diagnostics" tab in your scheme settings, enable "Main Thread Checker". While your app is running and attached to Xcode, warnings will appear in the warnings tab if any UIKit views are mutated in a background thread.

EXC_BAD_ACCESS Crash that we can't get rid of
 
 
Q