2012-08-31 47 views
5

我的代碼用於註冊使用UncaughtExceptionHandler未捕獲的異常處理程序目標C是如下,你認爲會有什麼潛在的問題?註冊的UncaughtExceptionHandler使用NSSetUncaughtExceptionHandler

@interface AppDelegate() 

void myHandler(NSException * exception); 

@end 

@implementation AppDelegate 

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

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

有沒有可能有一個更簡潔的方式來寫它?

我需要使用類擴展聲明原型,以擺脫以前沒有原型功能的警告..

回答

10

馬丁的答案是正確的:

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

+1像往常一樣的優秀解釋。 –

+1

感謝您的詳細解釋,而是指我的問題,'myHandler'被註冊在'AppDelegate',但未被捕獲的異常可以在任何類發生,所以如果我使用'static'是適合我的我不知道.. 。 – Ryan

+2

@Yoga:您可以在這裏毫無問題地使用'static',因爲您將'myHandler'的地址傳遞給'NSSetUncaughtExceptionHandler'。可見性只對鏈接器很重要。如果任何模塊的地址爲'myHandler',則可以獨立於可見性調用此函數。 - 將本地靜態函數的地址傳遞給其他函數是常見模式,例如,回調函數等 –

0

是的,這是正確的方式。我只是想知道爲什麼你得到警告,因爲我有同樣的事情,沒有一個空的類別宣佈它,我沒有得到一個警告。除此之外,你還可以設置信號處理程序捕捉SIGABRTSIGILLSIGBUS信號:

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

我敢打賭,你必須在生成設置中禁用的警告。 –

+0

PFF,是的,我一定已經忘記:) – graver

3

,如果你聲明的功能static你沒有得到一個關於失蹤原型警告。然而,我想我會詳細闡述一下,解釋爲什麼會這樣。

你的函數定義:

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

定義,這將是外部可見的功能。在其他(廣義的,非技術性的)單詞中,將在目標文件中創建一個符號,以便鏈接程序可以找到它,從而允許其他文件調用myHandler

然而,因爲它被認爲是外部可見,其他文件都將不得不知道的功能是什麼樣子。這就是原型發揮作用的地方。警告基本上是說......

嘿,你已經宣佈此功能是其他 代碼外部可見的,但我沒有看到一個原型,其他代碼可以使用它來了解 有關的功能。

所以,你會得到一個警告。這是一個很好的警告。它可以幫助您記住爲要導出的函數聲明原型。

現在,你發現,你可以聲明一個原型,並警告消失。但是,僅在實現文件中聲明原型應該是對您的另一個警告。該個人警告應該是:

您真的希望此功能具有外部可見性,還是僅在此編譯單元中調用?如果函數不具有外部可見性,則不需要將其導出到符號表中,也不需要其他模塊可以包含的原型,以便他們瞭解該函數。

在這種情況下,你可以聲明功能static在馬丁的回答是:

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

在此背景下,static告訴編譯器是這樣的:

嘿,編譯器,創建代碼此功能,並允許在 此編譯單元的任何代碼,看看功能,但不給它的外部 知名度。我不希望該功能被其他模塊調用。

在這種情況下,即使其他代碼聲明原型,它們也不會看到您的函數,因爲它對於定義它的文件是「私有」的。

由於它僅使用本地文件,也沒有必要爲原型,所以沒有必要提醒你,你沒有一個。

現在,就像一記...你並不需要把C函數在你的代碼的@interface和@implementation部分,如什麼也不做。這些C函數編譯時,無論它們是否在ObjC部分中,都具有完全相同的可見性和訪問權限。

最後,如果你願意,你可以禁用在Xcode構建設置這樣的警告(不過現在你瞭解警告的情況下,我建議離開它)。

+0

+1正如你一樣,你是對的。 –