Не удается обработать исключение с плавающей точкой (FPE) во второй раз - PullRequest
1 голос
/ 04 сентября 2010

Я написал программу, которая обрабатывает сигнал для исключения с плавающей точкой, и я использую Ubuntu 10.4.

Вот мой исходный код:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>

sigjmp_buf mark;

void GeneralHandler(int signo)
{
    switch(signo)
    {

        case SIGFPE:
            printf("\nERROR : Invalid Arithmetic operation.\n");
            siglongjmp(mark, signo);
            break;
    }

    exit(signo);
}

int main(void)
{
    int i = 0,value = 0, ans = 0;
    struct sigaction act;
    act.sa_handler = GeneralHandler;

    sigaction(SIGFPE, &act, NULL);

    for(i = 0; i < 10; i++)
    {
        if(sigsetjmp(mark, 1)) continue;
        printf("Value : ");
        scanf("%d" ,&value);
        ans = 5 / value;
        printf("%d / %d = %d\n", 5, value, ans);
    }

}

Я использую методы siglongjmp и sigsetjmp для перехода от метода-обработчика к основному методу внутри цикла.

Впервые работает нормально и отображает ОШИБКА: недопустимая арифметическая операция. , а затем отображает Исключение с плавающей запятой во второй раз и затем завершается.

Вывод программы:

searock @ searock-desktop: ~ / C $ ./signal_continue
Value: 0
ОШИБКА: неверная арифметическая операция.
Значение: 0
Исключение с плавающей запятой
searock @ searock- рабочий стол: ~ / C $

Я не уверен, что не так в моей программе? Почему не отображается ОШИБКА: неверная арифметическая операция. во второй раз? Может ли кто-нибудь указать мне правильное направление?

Ответы [ 2 ]

3 голосов
/ 04 сентября 2010

Вы не инициализировали struct sigaction Возможно act содержит значения мусора, например, для настройки обработчика сигнала на SA_RESETHAND или чего-то другого плохого.1008 *

или

memset(&act,0,sizeof act);
2 голосов
/ 04 сентября 2010

Не думаю, что вы должны logjump() из обработчика сигнала вернуться в основной код. Предполагается, что обработчик сигнала просто обрабатывает сигнал, а затем возвращается и позволяет основному выполнению программы идти в обычном режиме.

Я не уверен, что вы должны делать с SIGFPE. Страница руководства для signal() говорит, не очень многообещающе:

Согласно POSIX, поведение процесса после него не определено игнорирует сигнал SIGFPE, SIGILL или SIGSEGV, который не был сгенерирован убить (2) или поднять (3). Целочисленное деление на ноль имеет неопределенный результат. На некоторых архитектурах он генерирует сигнал SIGFPE. [...] Игнорирование этого сигнал может привести к бесконечной петле.

...