2010-09-04 2 views
1

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

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

#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-рабочий стол: ~/C $ ./signal_continue
Значение: 0
ОШИБКА: операция Invalid арифметика.
Значение: 0
плавающей запятой исключением
Searock @ Searock-рабочий стол: ~/C $

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

+1

Вы должны проверить возвращаемое значение из 'scanf()' и выйти из цикла, если оно не возвращается 1. –

ответ

3

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

Do структура

sigaction act = {}; 

или

memset(&act,0,sizeof act); 
+0

Является ли memset() частью posix или stdlib? – Searock

+1

@Searock - memset() является базовым стандартом (ISO) C; header ''. –

+0

Спасибо за подшипник со мной. Я новичок в Posix. – Searock

2

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

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

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

+0

Пожалуйста, несите меня, поскольку я новичок. Это вредно, если я продолжу программу после сигнала? – Searock

+2

@Searock: Как правило, сигналы представляют собой асинхронные события, которые обрабатываются отдельно обработчиком сигнала, основная программа на это прямо не влияет. Он должен (автоматически) продолжать работать как обычно, если обработчик сигнала не убил его в ответ на сигнал. Но я не эксперт по этой теме и не знаю, как вы должны реагировать на FPE. (Для деления на ноль, конечно, проблема в том, что основной программе все равно нужно будет произвести некоторый результат для этого выражения, если он хочет продолжить выполнение.) – sth

+0

Спасибо за объяснение. – Searock

Смежные вопросы