Вопрос

Как я могу эффективно отлавливать и обрабатывать ошибки сегментации из 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. Не очень хорошо задокументировано. Я попытался установить обработчик. Он скомпилировал и запустил, но не обнаружил ошибки.

Это было полезно?

Решение

Вы уверены, что не получаете 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top