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