In the iOS app I'm developing, I've noticed that since upgrading to iOS 17 (Xcode 15.1), crashes of this type occur frequently. The crashes are random and can't be reliably reproduced. Below is a typical crash report:
CrashReporter Key: fd24cf14a51d73ebfc1852cccb1b8d50822b247c
Hardware Model: iPhone11,2
Process: MyApp [89057]
Path: /private/var/containers/Bundle/Application/06B982E0-B818-48A9-B2D1-F28999EC3BC0/MyApp.app/MyApp
Identifier: com.company.MyApp
Version: 2.0.0 (72)
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.company.MyApp [4659]
Date/Time: 2024-03-24 14:50:46.3982 +0800
Launch Time: 2024-03-24 14:38:38.1438 +0800
OS Version: iPhone OS 17.3.1 (21D61)
Release Type: User
Baseband Version: 6.00.00
Report Version: 104
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x000000018c44e838
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Terminating Process: exc handler [89057]
Triggered by Thread: 0
Kernel Triage:
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x18c44e838 object_getClass + 48
1 Foundation 0x1930807b4 _NSKeyValueObservationInfoGetObservances + 264
2 Foundation 0x19307fc7c NSKeyValueWillChangeWithPerThreadPendingNotifications + 232
3 QuartzCore 0x19572f14c CAAnimation_setter(CAAnimation*, unsigned int, _CAValueType, void const*) + 128
4 QuartzCore 0x19574a6b4 -[CAAnimation setBeginTime:] + 52
5 QuartzCore 0x1957485b4 CA::Layer::commit_animations(CA::Transaction*, double (*)(CA::Layer*, double, void*), void (*)(CA::Layer*, CA::Render::Animation*, void*), void (*)(CA::Layer*, __CFString const*, void*), CA::Render::TimingList* (*)(CA::Layer*, void*), void*) + 740
6 QuartzCore 0x195700bf0 invocation function for block in CA::Context::commit_transaction(CA::Transaction*, double, double*) + 148
7 QuartzCore 0x195700af8 CA::Layer::commit_if_needed(CA::Transaction*, void (CA::Layer*, unsigned int, unsigned int) block_pointer) + 368
8-14QuartzCore 0x195700a84 CA::Layer::commit_if_needed(CA::Transaction*, void (CA::Layer*, unsigned int, unsigned int) block_pointer) + 252
15 QuartzCore 0x195745248 CA::Context::commit_transaction(CA::Transaction*, double, double*) + 11192
16 QuartzCore 0x19573bb80 CA::Transaction::commit() + 648
17 QuartzCore 0x19573b828 CA::Transaction::flush_as_runloop_observer(bool) + 88
18 CoreFoundation 0x1940ff7bc __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36
19 CoreFoundation 0x1940fe1c4 __CFRunLoopDoObservers + 548
20 CoreFoundation 0x1940fd8e0 __CFRunLoopRun + 1028
21 CoreFoundation 0x1940fd3f8 CFRunLoopRunSpecific + 608
22 GraphicsServices 0x1d768b4f8 GSEventRunModal + 164
23 UIKitCore 0x1965238a0 -[UIApplication _run] + 888
24 UIKitCore 0x196522edc UIApplicationMain + 340
25 MyApp 0x102c1f014 main + 140
26 dyld 0x1b6e52dcc start + 2240
By looking up information on the Exception Type and Termination Reason, I found that Apple officially mentions that EXC_BREAKPOINT (SIGTRAP) SIGNAL 5 Trace/BPT trap: 5 could be caused by Swift runtime error crashing mechanisms, mainly due to:
If you use the ! operator to force unwrap an optional value that’s nil, or if you force a type downcast that fails with the as! operator, the Swift runtime catches these errors and intentionally crashes the app.
For details, see the link: https://developer.apple.com/documentation/xcode/addressing-crashes-from-swift-runtime-errors
My project is a mix of Objc+Swift compilation, the crash usually occurs after a button click triggers a change in UIView properties, mostly related to layout. All Swift code in the project is unrelated to this type of UI. So, I speculate that it might not be related to Swift runtime errors, but I'm unsure what other possible causes could lead to the aforementioned crash.
A common denominator in all similar crash reports is that they occur on the main thread during system framework function calls,
All show multiple instances of
VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter
CA::Layer::commit_if_needed is always invoked. I noticed many crashes relate to CALayer setting properties internally calling CAAnimation, so I added:
@implementation CALayer (Animation)
/// Prevent crashes
+ (void)disableAnimation:(VoidBlock)block{
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
block();
[CATransaction commit];
}
@end
Using [CALayer disableAnimation:^{view.layer.someProperty = someValue;}]
to disable animations has prevented some crashes, but I'm powerless in situations like the stack trace above, where all calls are made by system frameworks.
I've also noticed other similar crash issues on forums: EXC_BREAKPOINT - libobjc.A.dylib object_getClass Crash on the main thread. The author experienced this issue after iOS 16 and iOS 17, with very similar stack information to mine.
I suspect other potential causes might include:
-
Whether it's related to KVO in UI code not being correctly released.
-
Whether it involves calls to GPU resources from other threads. I've rewritten most of the code to ensure no GPU-related image operations occur on other threads during CoreAnimation runtime.
-
Whether it's related to high memory usage and peak virtual memory. My app is related to image processing, and opening 4K photos for processing typically consumes more than 500MB of memory.
If you've encountered similar situations or can help identify potential causes, please advise. Many thanks!