Objective-C 在静态库中抛出异常。如何使用该库从程序中捕获异常?

Posted

技术标签:

【中文标题】Objective-C 在静态库中抛出异常。如何使用该库从程序中捕获异常?【英文标题】:Objective-C throwing an exception in a static library. How can I catch the exception from a program using the library? 【发布时间】:2018-02-24 18:03:19 【问题描述】:

我正在使用 Cocoa 编写一个静态库,并且 Xcode 项目包含一个“示例应用程序”目标。在库中,我创建了一个 NSException 对象并使用 raise 方法或 @trow 指令引发它。我没有成功捕获示例应用程序中的异常。我的代码是:

 @try 
        sdk = [SDK GetInstanceWithApiKey:@"12345"];

     @catch (NSException *exception) 
        NSLog(@"Exception:%@",exception);
    

不幸的是,应用程序没有进入 catch 块,它通常会崩溃,就像我在没有 try/catch 块的情况下调用构造函数一样。可能我错过了一些重要的东西。谢谢

在静态库中,这是我用来引发异常的代码:

NSException *exception = [[NSException alloc] initWithName:@"ConfigurationException" reason:@"Provided API Key is not valid." userInfo:NULL];

@throw exception;

这是日志中的崩溃报告:

2018-02-24 19:11:38.504384+0100 Example App[6585:366375] [General] An uncaught exception was raised
2018-02-24 19:11:38.504413+0100 Example App[6585:366375] [General] provided api key is not valid
2018-02-24 19:11:38.504475+0100 Example App[6585:366375] [General] (
    0   CoreFoundation                      0x00007fff3e757fcb __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x00007fff653f9c76 objc_exception_throw + 48
    2   Example App                         0x000000010000c701 -[raiseException:] + 273
    3   Example App                         0x0000000100005eff __84+[GetInstanceWithApiKey:sharedKey:productCode:licenseFilePath:]_block_invoke + 1567
    4   libdispatch.dylib                   0x000000010032dd1f _dispatch_client_callout + 8
    5   libdispatch.dylib                   0x000000010032dcff dispatch_once_f + 288
    6   Example App                         0x0000000100005800 +[GetInstanceWithApiKey:sharedKey:productCode:licenseFilePath:] + 400
    7   Example App                         0x0000000100001b6b -[AppDelegate applicationDidFinishLaunching:] + 91
    8   CoreFoundation                      0x00007fff3e6e7bbc __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    9   CoreFoundation                      0x00007fff3e6e7aaa _CFXRegistrationPost + 442
    10  CoreFoundation                      0x00007fff3e6e77f2 ___CFXNotificationPost_block_invoke + 50
    11  CoreFoundation                      0x00007fff3e6a5670 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1664
    12  CoreFoundation                      0x00007fff3e6a47a3 _CFXNotificationPost + 595
    13  Foundation                          0x00007fff40789467 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    14  AppKit                              0x00007fff3bde760a -[NSApplication _postDidFinishNotification] + 313
    15  AppKit                              0x00007fff3bde7253 -[NSApplication _sendFinishLaunchingNotification] + 220
    16  AppKit                              0x00007fff3bcb9f13 -[NSApplication(NSAppleEventHandling) _handleAEOpenEvent:] + 562
    17  AppKit                              0x00007fff3bcb9b49 -[NSApplication(NSAppleEventHandling) _handleCoreEvent:withReplyEvent:] + 690
    18  Foundation                          0x00007fff407cc404 -[NSAppleEventManager dispatchRawAppleEvent:withRawReply:handlerRefCon:] + 287
    19  Foundation                          0x00007fff407cc282 _NSAppleEventManagerGenericHandler + 102
    20  AE                                  0x00007fff3f7b7dd0 _Z20aeDispatchAppleEventPK6AEDescPS_jPh + 1788
    21  AE                                  0x00007fff3f7b7677 _ZL25dispatchEventAndSendReplyPK6AEDescPS_ + 41
    22  AE                                  0x00007fff3f7b7565 aeProcessAppleEvent + 383
    23  HIToolbox                           0x00007fff3d9f95e0 AEProcessAppleEvent + 55
    24  AppKit                              0x00007fff3bcb521e _DPSNextEvent + 2788
    25  AppKit                              0x00007fff3c44ab4c -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044
    26  AppKit                              0x00007fff3bca9d6d -[NSApplication run] + 764
    27  AppKit                              0x00007fff3bc78f1a NSApplicationMain + 804
    28  Example App                         0x0000000100001b02 main + 34
    29  libdyld.dylib                       0x00007fff65fe9115 start + 1
    30  ???                                 0x0000000000000003 0x0 + 3
)
2018-02-24 19:11:38.505511+0100 Example App[6585:366375] *** Terminating app due to uncaught exception 'LicenseConfigurationException', reason: 'provided api key is not valid'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff3e757fcb __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x00007fff653f9c76 objc_exception_throw + 48
    2   Example App                         0x000000010000c701 -[raiseException:] + 273
    3   Example App                         0x0000000100005eff __84+[GetInstanceWithApiKey:sharedKey:productCode:licenseFilePath:]_block_invoke + 1567
    4   libdispatch.dylib                   0x000000010032dd1f _dispatch_client_callout + 8
    5   libdispatch.dylib                   0x000000010032dcff dispatch_once_f + 288
    6   Example App                         0x0000000100005800 +[GetInstanceWithApiKey:sharedKey:productCode:licenseFilePath:] + 400
    7   Example App                         0x0000000100001b6b -[AppDelegate applicationDidFinishLaunching:] + 91
    8   CoreFoundation                      0x00007fff3e6e7bbc __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    9   CoreFoundation                      0x00007fff3e6e7aaa _CFXRegistrationPost + 442
    10  CoreFoundation                      0x00007fff3e6e77f2 ___CFXNotificationPost_block_invoke + 50
    11  CoreFoundation                      0x00007fff3e6a5670 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1664
    12  CoreFoundation                      0x00007fff3e6a47a3 _CFXNotificationPost + 595
    13  Foundation                          0x00007fff40789467 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    14  AppKit                              0x00007fff3bde760a -[NSApplication _postDidFinishNotification] + 313
    15  AppKit                              0x00007fff3bde7253 -[NSApplication _sendFinishLaunchingNotification] + 220
    16  AppKit                              0x00007fff3bcb9f13 -[NSApplication(NSAppleEventHandling) _handleAEOpenEvent:] + 562
    17  AppKit                              0x00007fff3bcb9b49 -[NSApplication(NSAppleEventHandling) _handleCoreEvent:withReplyEvent:] + 690
    18  Foundation                          0x00007fff407cc404 -[NSAppleEventManager dispatchRawAppleEvent:withRawReply:handlerRefCon:] + 287
    19  Foundation                          0x00007fff407cc282 _NSAppleEventManagerGenericHandler + 102
    20  AE                                  0x00007fff3f7b7dd0 _Z20aeDispatchAppleEventPK6AEDescPS_jPh + 1788
    21  AE                                  0x00007fff3f7b7677 _ZL25dispatchEventAndSendReplyPK6AEDescPS_ + 41
    22  AE                                  0x00007fff3f7b7565 aeProcessAppleEvent + 383
    23  HIToolbox                           0x00007fff3d9f95e0 AEProcessAppleEvent + 55
    24  AppKit                              0x00007fff3bcb521e _DPSNextEvent + 2788
    25  AppKit                              0x00007fff3c44ab4c -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044
    26  AppKit                              0x00007fff3bca9d6d -[NSApplication run] + 764
    27  AppKit                              0x00007fff3bc78f1a NSApplicationMain + 804
    28  Example App                         0x0000000100001b02 main + 34
    29  libdyld.dylib                       0x00007fff65fe9115 start + 1
    30  ???                                 0x0000000000000003 0x0 + 3
)
libc++abi.dylib: terminating with uncaught exception of type NSException

【问题讨论】:

请显示你提出的相关代码和你得到的堆栈跟踪。 如果你改用@catch(...) 会怎样? 谢谢马特,不幸的是同样的结果 -applicationDidFinishLaunching: 中的第一个 sn-p 是您代码中的唯一实例吗? 这对我来说在一个新项目中效果很好。我建议你回到一个最小的例子。它必须是项目设置中的内容。 【参考方案1】:

您的代码看起来不错。在 Apple 上找到了这个 - https://developer.apple.com/library/content/technotes/tn2151/_index.html

查看“清单 11”,它说明了这一点:

注意:如果您发现在您的应用程序设置的异常处理域中抛出的异常没有被捕获,请确认您在构建应用程序或库时没有指定 -no_compact_unwind 标志。

因此,如果该标志在您的构建设置中,您可能需要删除它。

【讨论】:

感谢您的帮助,不幸的是,我在库或示例应用程序中都没有此选项

以上是关于Objective-C 在静态库中抛出异常。如何使用该库从程序中捕获异常?的主要内容,如果未能解决你的问题,请参考以下文章

如何在扩展中抛出异常?

如何在 C 中抛出异常?

如何在 Symfony2 中抛出 403 异常?

库中静态分配的 zlib 字节数组上的 memset 使 Objective-C++ 程序崩溃

如何捕获ctypes中抛出的异常?

如何捕获 node_modules 中抛出的异常