使用NSSetUncaughtExceptionHandler在Objective C中注册UncaughtExceptionHandler

时间:2012-08-31 12:04:20

标签: iphone objective-c ios c xcode

我使用UncaughtExceptionHandler注册未捕获的异常处理程序的代码如下,您认为会有任何潜在的问题吗?

@interface AppDelegate ()

void myHandler(NSException * exception);

@end

@implementation AppDelegate

void myHandler(NSException * exception)
{
  // ...
}

- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSSetUncaughtExceptionHandler(&myHandler);
..

是否有可能以更简洁的方式编写它?

我需要使用类扩展来声明原型,以便摆脱没有以前的函数原型的警告..

3 个答案:

答案 0 :(得分:10)

马丁的回答是正确的。但是,我想我会详细说明一下,为什么会这样解释。

您的功能定义:

void myHandler(NSException * exception)
{
  // ...
}

定义一个外部可见的函数。在其他(通用的,非技术的)单词中,将在目标文件中创建一个符号,以便链接器可以找到它,这允许其他文件调用myHandler

但是,因为它应该在外部可见,所以其他文件必须知道该函数的外观。这就是原型发挥作用的地方。警告基本上是在说......

  

嘿,你已宣布这个功能在外部对其他人可见   代码,但我没有看到其他代码可以用来知道的原型   关于功能。

所以,你得到一个警告。这是一个很好的警告。它可以帮助您记住为要导出的函数声明原型。

现在,正如您所发现的那样,您可以声明原型,并且警告消失了。但是,在实现文件中声明原型应该是另一个警告。个人警告应该是:

您真的希望此函数具有外部可见性,还是仅在此编译单元中调用?如果该函数不具有外部可见性,则无需将其导出到符号表中,并且不需要其他模块可以包含的原型,因此他们知道该函数。

在这种情况下,您可以像Martin的回复一样声明函数static

static void myHandler(NSException * exception)
{
  // ...
}

在此上下文中,static告诉编译器类似于:

  

嘿,编译器,为这个函数创建代码,并允许任何代码   这个编译单元看功能,但不要给它外部   能见度。我不希望其他模块调用该函数。

在这种情况下,即使其他代码声明了原型,它们也不会看到你的函数,因为它对定义它的文件是“私有的”。

由于它仅在本地文件中使用,因此不需要原型,因此无需警告您没有原型。

现在,就像一个注释......你不需要在代码的@interface和@implementation部分放置C函数,因为它什么都不做。无论是否在ObjC部分内,这些C函数都具有完全相同的可见性和访问权。

最后,如果您愿意,可以在Xcode构建设置中禁用此警告(但现在您已了解警告的上下文,我建议将其保留)。

答案 1 :(得分:3)

如果您将函数声明为static,则不会收到有关缺少原型的警告:

static void myHandler(NSException * exception)
{
  // ...
}

答案 2 :(得分:0)

是的,这是正确的方法。我只是想知道为什么你得到警告,因为我有同样的事情而没有在空类别中声明它并且我没有得到警告......此外你还可以设置信号处理程序以捕获SIGABRTSIGILLSIGBUS信号:

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);
    ...
}