2009-03-05 27 views
3

如何在OSX Carbon應用程序中有效捕獲和處理來自C的分段錯誤?OSX Carbon C應用程序的例外包裝器

背景:我正在製作OSX Carbon應用程序。我必須從第三方調用圖書館功能。由於線程問題,函數可能偶爾會崩潰,通常是因爲它是從一個線程更新自己的,並且當我從另一個線程查詢它時,它有一些內部陳舊的指針或句柄。該功能對我來說是一個黑匣子。我希望能夠調用這個函數,但是如果它已經崩潰並且提供了另一個回報,就能夠「捕捉」它。 在Windows中,我可以使用簡單的Visual C和Intel C編譯器的__try {}和__except。

/* Working Windows Example */ 
__try { x=DangerousFunction(y);} 
__except(EXCEPTION_EXECUTE_HANDLER) {x=0.0;} /* whups, func crashed! */ 

我想爲OSX製造同樣的crash-catcher。我在一個非常大的應用程序上使用純C語言。我每秒調用這個函數數百萬次,所以效率也非常重要。 (令人印象深刻,在Windows __try()的開銷是沒法比的小!)

這就是我有嘗試:

1)C++異常。我不確定C++異常是否會捕獲段錯誤。而我的應用程序目前是C.我可以嘗試包裝和#ifdefs使它成爲C++,但這是應用程序的很多工作,我不認爲C++異常會趕上崩潰。

2)signal + setjump + longjmp。我認爲這會工作......這是它的目的。但是我設置了我的SEGV錯誤處理程序[事實上,我爲每個信號都設置了它],並且在崩潰期間它從來沒有被調用過。調用raise(SEGV)時,我可以手動測試(併成功)。但這些崩潰似乎並沒有真正稱之爲。我的想法是,CFM應用程序不能訪問完整的BSD信號,只有一個子集,並且Mach應用程序對Real Thing是必需的。

3)MPSetExceptionHandler。沒有很好的記錄。我試圖設置一個處理程序。它編譯並運行,但沒有捕捉到段錯誤。

回答

3

你確定你沒有得到SIGBUS而不是SIGSEGV嗎?下面

的捕獲SIGBUS引起的試圖在存儲單元0寫:

cristi:tmp diciu$ cat test.c 

#include <signal.h> 

static void sigac(int sig) 
{ 
    printf("sig action here, signal is %d\n", sig); 
    exit(1); 
} 

int main() 
{ 
    (void)signal(SIGSEGV, sigac); 
    (void)signal(SIGBUS, sigac); 

    printf("Raising\n"); 
    strcpy(0, "aaksdjkajskd|"); 
} 



cristi:tmp diciu$ ./a.out 
Raising 
sig action here, signal is 10 
+0

是。我認爲關鍵是抓住每種類型的每個異常! – SPWorley 2009-03-24 07:29:48