Исключительная оболочка для приложения Carbon C в OSX - PullRequest
3 голосов
/ 05 марта 2009

Как эффективно отлавливать и обрабатывать ошибки сегментации из C в приложении OSX Carbon?

Справочная информация: я делаю приложение 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. Я использую чистый C в очень большом приложении. Я вызываю функцию миллионы раз в секунду, поэтому эффективность тоже очень важна. (Впечатляет, что накладные расходы Windows __try () неизмеримо малы!)

Вот что я экспериментировал с:

1) Исключения в C ++. Я не уверен, что исключения C ++ ловят сбои segfault. И мое приложение в настоящее время C. Я мог бы попробовать обертки и #ifdefs, чтобы сделать его C ++, но это большая работа для приложения, и я не думаю, что исключения C ++ вызовут сбой.

2) сигнал + setjump + longjmp. Я думал, что это будет работать ... это то, для чего он предназначен. Но я настроил свой обработчик ошибок SEGV (на самом деле я установил его для каждого сигнала!), И он никогда не вызывался во время сбоя. Я могу вручную (и успешно) при вызове рейза (SEGV). Но сбои, кажется, на самом деле не называют это. Я думаю, что приложения CFM НЕ имеют доступа к полным сигналам BSD, только подмножество, и что приложения Маха необходимы для реальной вещи.

3) MPSetExceptionHandler. Не очень хорошо задокументировано. Я попытался установить обработчик. Он скомпилировал и запустил, но не перехватил segfault.

1 Ответ

3 голосов
/ 05 марта 2009

Вы уверены, что не получаете 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
...