5

我注册未捕获异常处理程序的代码UncaughtExceptionHandler如下,你认为会有什么潜在的问题吗?

@interface AppDelegate ()

void myHandler(NSException * exception);

@end

@implementation AppDelegate

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

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

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

我需要使用类扩展来声明原型,以摆脱No previous prototype for function 的警告。

4

3 回答 3

11

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

您的函数定义:

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

定义一个外部可见的函数。换句话说(广义的、非技术性的),将在目标文件中创建一个符号,以便链接器可以找到它,从而允许其他文件调用myHandler.

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

嘿,您已声明此函数对其他代码在外部可见,但我没有看到其他代码可以用来了解该函数的原型。

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

现在,正如您所发现的,您可以声明一个原型,警告就会消失。但是,仅在实现文件中声明原型应该是对您的另一个警告。个人警告应该是:

你真的希望这个函数具有外部可见性,还是只是在这个编译单元中调用它?如果函数不具有外部可见性,则不需要将其导出到符号表中,也不需要其他模块可以包含的原型以便他们了解该函数。

static在这种情况下,您可以按照 Martin 的响应声明该函数:

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

在这种情况下,static告诉编译器类似:

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

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

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

现在,就像一个注释......您不需要将 C 函数放在代码的 @interface 和 @implementation 部分中,因为这没有任何作用。这些 C 函数在编译时具有完全相同的可见性和访问权限,无论它们是否位于 ObjC 部分中。

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

于 2012-08-31T13:36:25.633 回答
3

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

static void myHandler(NSException * exception)
{
  // ...
}
于 2012-08-31T12:44:22.157 回答
0

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

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);
    ...
}
于 2012-08-31T12:40:01.387 回答