Home > Blockchain >  'runtime_error' from c not captured in iOS
'runtime_error' from c not captured in iOS

Time:07-15

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?

CodePudding user response:

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 (...) {
}
  • Related