Search code examples
c++iosswiftobjective-cruntime-error

'runtime_error' from c++ not captured in iOS


In my iOS project, I use a C++ module. The C++ module throws exception for some cases and the Objective C++ wrapper fails to catch it. For instance

Here is my HelloWorld.h

#include <string>
using namespace std;

class HelloWorld{
public:
    string helloWorld();
};

#endif

Implementation HelloWorld.cpp

#include "HelloWorld.h"

string HelloWorld::helloWorld(){
    throw (std::runtime_error("runtime_error")); // Throwing exception to test
    string s("Hello from CPP");
    return s;
}

Objective C++ wrapper HelloWorldIOSWrapper.h

#import <Foundation/Foundation.h>

@interface HelloWorldIOSWrapper:NSObject

- (NSString*)getHello;

@end

#endif /* HelloWorldIOSWrapper_h */

Implementation HelloWorldIOSWrapper.mm

#import "HelloWorldIOSWrapper.h"
#include "HelloWorld.h"

@implementation HelloWorldIOSWrapper

- (NSString*)getHello{
    try {
        HelloWorld h;
        NSString *text=[NSString stringWithUTF8String: h.helloWorld().c_str()];
        return text;
    } catch (const std::exception & e) {
        NSLog(@"Error %s", e.what());
    }
    return nil;
}

@end

#import "HelloWorldIOSWrapper.h" is added to the Bridging-Header

And now, when I try to invoke getHello() from controller, app crashes leaving the below message in log

libc++abi: terminating with uncaught exception of type std::runtime_error: runtime_error
dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
terminating with uncaught exception of type std::runtime_error: runtime_error

I expect that the exception must be caught in the wrapper, but, no idea why is it not caught leading to app crash. What do I miss?


Solution

  • C++ Interoperability

    In 64-bit processes, Objective-C exceptions (NSException) and C++ exception are interoperable. Specifically, C++ destructors and Objective-C @finally blocks are honored when the exception mechanism unwinds an exception. In addition, default catch clauses—that is, catch(...) and @catch(...)—can catch and rethrow any exception

    On the other hand, an Objective-C catch clause taking a dynamically typed exception object (@catch(id exception)) can catch any Objective-C exception, but cannot catch any C++ exceptions. So, for interoperability, use @catch(...) to catch every exception and @throw; to rethrow caught exceptions. In 32-bit, @catch(...) has the same effect as @catch(id exception).

    @try {
    } 
    @catch (...) {
    }