使用NSSetUncaughtExceptionHandler在Objective C中注册UncaughtExceptionHandler
我使用UncaughtExceptionHandler
注册未捕获exception处理程序的代码如下,你认为会有什么潜在的问题吗?
@interface AppDelegate () void myHandler(NSException * exception); @end @implementation AppDelegate void myHandler(NSException * exception) { // ... } - (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSSetUncaughtExceptionHandler(&myHandler); ..
有没有可能有一个更简洁的方式来写它?
我需要使用类扩展来声明原型,以摆脱没有以前的function原型的警告。
马丁的答案是正确的。 不过,我想我会详细阐述一下,解释为什么是这样。
你的函数定义:
void myHandler(NSException * exception) { // ... }
定义了一个外部可见的函数。 在其他(通用的,非技术性的)单词中,将在目标文件中创build一个符号,以便链接程序可以find它,从而允许其他文件调用myHandler
。
但是,因为它应该是外部可见的,所以其他文件将不得不知道该函数是什么样的。 这就是原型发挥作用的地方。 警告基本上是说…
嘿,你已经声明了这个函数在其他代码的外部是可见的,但是我没有看到其他代码可以用来了解这个函数的原型。
所以,你得到一个警告。 这是一个很好的警告。 它可以帮助您记住为要导出的函数声明原型。
现在,如你所发现的,你可以声明一个原型,并且警告消失。 但是,在实现文件中声明原型应该是对您的另一个警告。 那个人的警告应该是:
你真的希望这个函数具有外部可见性,还是只在这个编译单元中调用? 如果函数不具有外部可见性,则不需要将其导出到符号表中,也不需要其他模块可以包含的原型,以便了解该函数。
在这种情况下,你可以像马丁的回应一样声明static
函数:
static void myHandler(NSException * exception) { // ... }
在这种情况下, static
告诉编译器如下所示:
嘿,编译器,为这个函数创build代码,并允许这个编译单元中的任何代码看到这个函数,但是不要给它外部的可见性。 我不希望这个函数被其他模块调用。
在这种情况下,即使其他代码声明了原型,它们也不会看到你的函数,因为它对于定义它的文件是“私有”的。
由于它只用于本地文件,因此不需要原型,所以不需要警告你没有原型。
现在,就像注释一样…您不需要将C函数放在代码的@interface和@implementation部分,因为它什么也不做。 这些C函数编译时,无论它们是否在ObjC部分中,都具有完全相同的可见性和访问权限。
最后,如果你愿意的话,你可以在Xcode构build设置中禁用这个警告(但是现在你明白了警告的上下文,我build议将它留下)。
如果将函数声明为static
则不会收到有关缺less原型的警告:
static void myHandler(NSException * exception) { // ... }
是的,这是正确的方法。 我只是想知道为什么你会得到这样的警告,因为我有同样的事情,没有声明它在一个空的类别,我没有得到一个警告…另外,你也可以设置信号处理程序捕获SIGABRT
, SIGILL
和SIGBUS
信号:
void signalHandler(int sig) { } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { struct sigaction newSignalAction; memset(&newSignalAction, 0, sizeof(newSignalAction)); newSignalAction.sa_handler = &signalHandler; sigaction(SIGABRT, &newSignalAction, NULL); sigaction(SIGILL, &newSignalAction, NULL); sigaction(SIGBUS, &newSignalAction, NULL); ... }