EXC_BREAKPOINT @main

I'm getting the following error @main: Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1886cdcf8). It occurs about every other time someone attempts to log in to the app. Also I cannot replicate this issue on the simulator -- only on physical devices.

Answered by samrshi in 785827022

Hey there, I'm the TA/mentor for the team who encountered this issue. I met with them to debug this afternoon, and I cautiously believe we may have made some progress.

tl;dr: I believe there may be a bug when removing a NavigationView from the view hierarchy while it's presenting a child view.

Their crash occurred when a user pressed their "sign in" button with valid credentials. After the backend validates the credentials, they update an @Published property containing their authentication state, which they essentially switch over in their ContentView. Here's a simplified version of their ContentView:

struct ContentView: View {
    @ObservedObject var manager = AuthenticationManager.shared

    var body: some View {
        if manager.state == .loggedIn {
            MainView()
        } else if manager.state == .loading {
            ProgressView()
        } else {
            AuthView()
        }
    }
}

After the credentials are validated, they transition their auth state to .loading while fetching their user information. This is the point where the app crashed. So, it seemed like the crash might have been occurring during the deallocation of AuthView(), which has a NavigationView as its root view (which aligns with the [UINavigationController dealloc] calls in the backtrace).

I noticed references to UISplitViewController in the backtrace and, since they only ever need NavigationViewStyle.stack, I decided to try replacing NavigationView with NavigationStack. After that change, we haven't been able to reproduce the crash.

I found a minimum sample project that reproduces this crash, so I believe this might be a bug in SwiftUI/UIKit. I'll file a feedback with that code shortly.

I was getting a sensitive content error when trying to post my crash log so i've uploaded it to google drive. [crashlog](https://drive.google.com/file/d/1LskFOLdL1X4qvvqhvaOLp31XEwNME6SO/view?usp=drive_link

If you can reproduce it on a physical device, why can't you debug it yourself? Just connect the device to Xcode, run the app and see where it breaks?

I was getting a sensitive content error

Please try posting it again. There’s something weird afoot with posting crash reports (see Problems attaching crash reports?) and I’d like to know if this problem has gone away now.

The crash report you posted shows your app dying while tracking to access invalid memory:

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0f00000b00000000 …

That point is way off in the weeds, suggesting some sort of memory corruption issue. That’s reinforced by the crashing thread’s backtrace:

Thread 0 Crashed:
0   libobjc.A.dylib        … lookUpImpOrForward + 72
1   libobjc.A.dylib        … _objc_msgSend_uncached + 68
2   UIKitCore              … -[UIViewController dealloc] + 860
3   UIKitCore              … -[UINavigationController dealloc] + 296
4   UIKitCore              … -[_UISplitViewControllerColumnContents .cxx_destruct] + 44
5   libobjc.A.dylib        … object_cxxDestructFromClass(objc_object*, objc_class*) + 116
6   libobjc.A.dylib        … objc_destructInstance + 80
7   libobjc.A.dylib        … _objc_rootDealloc + 80
8   CoreFoundation         … cow_cleanup + 164
9   CoreFoundation         … -[__NSDictionaryM dealloc] + 148
10  libobjc.A.dylib        … object_cxxDestructFromClass(objc_object*, objc_class*) + 116
11  libobjc.A.dylib        … objc_destructInstance + 80
12  libobjc.A.dylib        … _objc_rootDealloc + 80
13  UIKitCore              … -[UISplitViewControllerPanelImpl dealloc] + 100
14  libobjc.A.dylib        … object_cxxDestructFromClass(objc_object*, objc_class*) + 116
15  libobjc.A.dylib        … objc_destructInstance + 80
16  libobjc.A.dylib        … _objc_rootDealloc + 80
17  UIKitCore              … -[UIResponder dealloc] + 124
18  UIKitCore              … -[UIViewController dealloc] + 1172
19  libsystem_blocks.dylib … bool HelperBase<GenericInline>::disposeCapture<(HelperBase<GenericInline>::BlockCa…
20  libsystem_blocks.dylib … HelperBase<GenericInline>::destroyBlock(Block_layout*, bool, unsigned char*) + 160
21  libsystem_blocks.dylib … _call_dispose_helpers_excp + 72
22  libsystem_blocks.dylib … _Block_release + 252
23  UIKitCore              … -[_UIAfterCACommitBlock run] + 84
24  UIKitCore              … -[_UIAfterCACommitQueue flush] + 164
25  UIKitCore              … _runAfterCACommitDeferredBlocks + 496
26  UIKitCore              … _cleanUpAfterCAFlushAndRunDeferredBlocks + 100
27  UIKitCore              … _UIApplicationFlushCATransaction + 72
28  UIKitCore              … _UIUpdateSequenceRun + 84
29  UIKitCore              … schedulerStepScheduledMainSection + 144
30  UIKitCore              … runloopSourceCallback + 92
31  CoreFoundation         … __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
32  CoreFoundation         … __CFRunLoopDoSource0 + 176
33  CoreFoundation         … __CFRunLoopDoSources0 + 244
34  CoreFoundation         … __CFRunLoopRun + 828
35  CoreFoundation         … CFRunLoopRunSpecific + 608
36  GraphicsServices       … GSEventRunModal + 164
37  UIKitCore              … -[UIApplication _run] + 888
38  UIKitCore              … UIApplicationMain + 340
39  SwiftUI                … 0x198438000 + 16988256
40  SwiftUI                … 0x198438000 + 16987816
41  SwiftUI                … 0x198438000 + 12909052
42  UNC-Golf               … 0x100660000 + 380404
43  dyld                   … start + 2240

My general advice in cases like this is to apply the standard memory debugging tools.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Looks like I can post crashlogs now.

As far as using the standard memory debugging tools, I've unfortunately already tried this. The problem is that when i try to trace where its occurring, it just throws Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1886cdcf8) at main. I'm sure it's actually crashing somewhere deeper in the code, but i'm not sure how to figure out where. I'm pretty new to iOS development, so it's possible I'm doing something wrong here. Any suggestions?

Looks like I can post crashlogs now.

Cool.

The problem is that when i try to trace where its occurring, it just throws Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1886cdcf8) at main.

These are different problems. Your crash report shows a memory access exception, which is EXC_BAD_ACCESS. The EXC_BREAKPOINT exception is more commonly associated with a trap, that is, some code within your process has detected an internal failure and deliberately crashed.

These may be related though. The crash report for your EXC_BREAKPOINT crash may reveal something interesting. Please post that.

Posting a Crash Report explains how to get a crash report when you’ve crashed into the Xcode debugger.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

With Zombies turned on, I get EXC_BREAKPOINT. Here is that crashlog.

With Zombies turned off, I get EXC_BAD_ACCESS. For the sake of clarity, here is that crashlog.

Thanks!

With Zombies turned on, I get EXC_BREAKPOINT.

Ah, that’s great news. It suggests that zombies is doing what it’s supposed to be doing, that is, causing the crash to occur sooner, and in a controlled manner, rather than later, after the state necessary to debug the problem has been destroyed.

The crashing thread backtrace looks like this:

Thread 0 name:   Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   CoreFoundation         … ___forwarding___.cold.2 + 92
1   CoreFoundation         … ___forwarding___ + 1292
2   CoreFoundation         … _CF_forwarding_prep_0 + 96
3   UIKitCore              … -[UIViewController dealloc] + 860
4   UIKitCore              … -[UINavigationController dealloc] + 296
5   UIKitCore              … -[_UISplitViewControllerColumnContents .cxx_destruct] + 44
6   libobjc.A.dylib        … object_cxxDestructFromClass(objc_object*, objc_class*) + 116
7   libobjc.A.dylib        … objc_destructInstance + 80
8   CoreFoundation         … -[NSObject(NSObject) __dealloc_zombie] + 152
9   CoreFoundation         … cow_cleanup + 164
10  CoreFoundation         … -[__NSDictionaryM dealloc] + 148
11  libobjc.A.dylib        … object_cxxDestructFromClass(objc_object*, objc_class*) + 116
12  libobjc.A.dylib        … objc_destructInstance + 80
13  CoreFoundation         … -[NSObject(NSObject) __dealloc_zombie] + 152
14  UIKitCore              … -[UISplitViewControllerPanelImpl dealloc] + 100
15  libobjc.A.dylib        … object_cxxDestructFromClass(objc_object*, objc_class*) + 116
16  libobjc.A.dylib        … objc_destructInstance + 80
17  CoreFoundation         … -[NSObject(NSObject) __dealloc_zombie] + 152
18  UIKitCore              … -[UIResponder dealloc] + 124
19  UIKitCore              … -[UIViewController dealloc] + 1172
20  libsystem_blocks.dylib … bool HelperBase::disposeCapture<(HelperBase::BlockCaptureKind)3>(unsigned int, uns…
21  libsystem_blocks.dylib … HelperBase::destroyBlock(Block_layout*, bool, unsigned char*) + 160
22  libsystem_blocks.dylib … _call_dispose_helpers_excp + 72
23  libsystem_blocks.dylib … _Block_release + 252
24  UIKitCore              … -[_UIAfterCACommitBlock run] + 84
25  UIKitCore              … -[_UIAfterCACommitQueue flush] + 164
26  UIKitCore              … _runAfterCACommitDeferredBlocks + 496
27  UIKitCore              … _cleanUpAfterCAFlushAndRunDeferredBlocks + 100
28  UIKitCore              … _UIApplicationFlushCATransaction + 72
29  UIKitCore              … _UIUpdateSequenceRun + 84
30  UIKitCore              … schedulerStepScheduledMainSection + 144
31  UIKitCore              … runloopSourceCallback + 92
32  CoreFoundation         … __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
33  CoreFoundation         … __CFRunLoopDoSource0 + 176
34  CoreFoundation         … __CFRunLoopDoSources0 + 244
35  CoreFoundation         … __CFRunLoopRun + 828
36  CoreFoundation         … CFRunLoopRunSpecific + 608
37  GraphicsServices       … GSEventRunModal + 164
38  UIKitCore              … -[UIApplication _run] + 888
39  UIKitCore              … UIApplicationMain + 340
40  SwiftUI                … 0x19840c000 + 16988256
41  SwiftUI                … 0x19840c000 + 16987816
42  SwiftUI                … 0x19840c000 + 12909052
43  UNC-Golf               … static UNC_GolfApp.$main() + 40
44  UNC-Golf               … main + 12
45  dyld                   … start + 2240

That’s not super enlightening. Almost everything in the backtrace is system code. The only thing of interest in frame 19, showing a view controller being deallocated, and frame 3, showing another view controller being deallocated. That suggests some sort of nested view controller setup, where the inner view controlling is release an object that’s gone bad somehow.

Thread 19 in the backtrace suggests you have ASan turned on. It’s generally not best to combine debugging tools like this. So, if you run the app with just zombies, does it still crash? If so, please post that crash report.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Interesting. It does still crash with only zombies. Here is that crashlog.

Thanks for the latest crash report.

Zombies usually spits out a log message explaining the problem that it found. Do you see that? Choose View > Debug Areas > Activate Console.

Next, if you run the app under Instruments using the Zombies template, does that also reveal the zombie?

If it does, that’ll be super helpful because the Zombies instrument lets you see all the reference count manipulations on the object that lead up to the failure.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

Hey there, I'm the TA/mentor for the team who encountered this issue. I met with them to debug this afternoon, and I cautiously believe we may have made some progress.

tl;dr: I believe there may be a bug when removing a NavigationView from the view hierarchy while it's presenting a child view.

Their crash occurred when a user pressed their "sign in" button with valid credentials. After the backend validates the credentials, they update an @Published property containing their authentication state, which they essentially switch over in their ContentView. Here's a simplified version of their ContentView:

struct ContentView: View {
    @ObservedObject var manager = AuthenticationManager.shared

    var body: some View {
        if manager.state == .loggedIn {
            MainView()
        } else if manager.state == .loading {
            ProgressView()
        } else {
            AuthView()
        }
    }
}

After the credentials are validated, they transition their auth state to .loading while fetching their user information. This is the point where the app crashed. So, it seemed like the crash might have been occurring during the deallocation of AuthView(), which has a NavigationView as its root view (which aligns with the [UINavigationController dealloc] calls in the backtrace).

I noticed references to UISplitViewController in the backtrace and, since they only ever need NavigationViewStyle.stack, I decided to try replacing NavigationView with NavigationStack. After that change, we haven't been able to reproduce the crash.

I found a minimum sample project that reproduces this crash, so I believe this might be a bug in SwiftUI/UIKit. I'll file a feedback with that code shortly.

I can confirm that switching NavigationView to NavigationStack fixes the issue for us as well.

It began happening to us when updating the app using the iOS 18 SDK, and maintaining both a NavigationView and NavigationStack code branches is mental.

EXC_BREAKPOINT @main
 
 
Q