First up, I have nothing new to report regarding this bug (r. 50481364). However, I recently stumbled across something that might be of interest for folks in this situation, namely, the C++ noexcept
modifier.
Consider this Objective-C++ code:
1 #import "AppDelegate.h"
2
…
25
26 @implementation AppDelegate {
27 Monkey * _monkey;
28 }
29
30 @synthesize window = _window;
31
…
45 - (IBAction)seeAction:(id)sender {
46 #pragma unused(sender)
47 self->_monkey->see();
48 }
49
50 - (IBAction)hearAction:(id)sender {
51 #pragma unused(sender)
52 self->_monkey->hear();
53 }
54
55 - (IBAction)speakAction:(id)sender {
56 #pragma unused(sender)
57 auto ok = noexcept( self->_monkey->speak() );
58 assert(ok);
59 }
60
61 @end
which calls through to this C++ back end:
class Monkey {
public:
void see() {
this->evil();
}
void hear() noexcept {
this->evil();
}
void speak() {
this->evil();
}
private:
void evil() {
throw 42;
}
};
In the -seeAction:
case you get this in the crash report:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib … __pthread_kill + 8
1 libsystem_pthread.dylib … pthread_kill + 288
2 libsystem_c.dylib … abort + 180
3 libc++abi.dylib … abort_message + 132
4 libc++abi.dylib … demangling_terminate_handler() + 348
5 libobjc.A.dylib … _objc_terminate() + 160
6 libc++abi.dylib … std::__terminate(void (*)()) + 16
7 libc++abi.dylib … __cxa_rethrow + 148
8 libobjc.A.dylib … objc_exception_rethrow + 44
9 AppKit … -[NSApplication _handleEvent:] + 120
which is not helpful.
Note This on macOS 14.1.2. I’m building with Xcode 15.0. The noexcept
modifier is supported in C++11 and later.
OTOH, in the -hearAction:
case, where the underlying C++ method is marked as noexcept
, you get this:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib … __pthread_kill + 8
1 libsystem_pthread.dylib … pthread_kill + 288
2 libsystem_c.dylib … abort + 180
3 libc++abi.dylib … abort_message + 132
4 libc++abi.dylib … demangling_terminate_handler() + 348
5 libobjc.A.dylib … _objc_terminate() + 160
6 libc++abi.dylib … std::__terminate(void (*)()) + 16
7 libc++abi.dylib … std::terminate() + 56
8 TestNoExcept … -[AppDelegate hearAction:] + 64 (AppDelegate.mm:52)
9 AppKit … -[NSApplication(NSResponder) sendAction:to:from:] + 460
Because the method is noexcept
, the runtime traps when you throw an exception out of it. That’s a noticeable improvement, in that at least you can tell where the C++ code broke its contract.
The -speakAction:
case is for when you’re unable to decorate your C++ method with noexcept
. It results in this:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib … __pthread_kill + 8
1 libsystem_pthread.dylib … pthread_kill + 288
2 libsystem_c.dylib … abort + 180
3 libsystem_c.dylib … __assert_rtn + 284
4 TestNoExcept … -[AppDelegate speakAction:] + 88 (AppDelegate.mm:58)
5 AppKit … -[NSApplication(NSResponder) sendAction:to:from:] + 460
You could, of course, wrap this in a macro or function that makes it a bit less clunky.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"