Как поднять различные исключения с плавающей запятой в C? - PullRequest
0 голосов
/ 27 июня 2019

Я заинтересован в повышении исключений с плавающей запятой, таких как Division by zero, Overflow, Underflow и т. Д.

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

Я использую функции в fenv.h. Во-первых, я включаю прерывание, используя feenableexcept и затем я вызываю исключение, используя feraiseexcept.

#define _GNU_SOURCE
#include <fenv.h>
#include <stdio.h>


int main(void) {
    feenableexcept(FE_UNDERFLOW);

    feraiseexcept(FE_OVERFLOW);

    return 0;
}

Сообщение, отображаемое в терминале:

Floating point exception (core dumped)

Вместо этого я хочу сообщение этой формы

Overflow

Я также пытался работать с SIGFPE. Поскольку для каждого исключения с плавающей запятой возникает один и тот же сигнал SIGPE, это не помогает дифференцировать различные причины сигнала. Существует аналогичный вопрос о переполнении стека, на который нет удовлетворительного ответа.

Мы можем использовать fetestexcept (FE_OVERFLOW), но это должно быть точно записано после каждой операции с плавающей запятой для проверки на переполнение.

Примечание: я компилирую свою программу, используя

gcc test_float -lm

редактировать

Я попытался поймать SIGFPE и написал эту программу

#define _GNU_SOURCE
#include <fenv.h>
#include <stdio.h> 
#include <signal.h>
#include <stdlib.h>

void catch_fpe (int sig) {   

    //#pragma STDC FENV_ACCESS ON
    printf("i am in catch_fpe\n");
    if(fetestexcept(FE_OVERFLOW))
        printf("OVERFLOW\n");
    else if(fetestexcept(FE_UNDERFLOW))
        printf("UNDERFLOW\n");
    else if(fetestexcept(FE_DIVBYZERO))
        printf("DIVBYZERO\n");
    else if(fetestexcept(FE_INVALID))
        printf("INVALID OPERATION\n");
    else if(fetestexcept(FE_INEXACT))
        printf("INEXACT RESULT\n");

    exit(0);
}

int main()
{
    feclearexcept(FE_ALL_EXCEPT);
    feenableexcept(FE_INVALID   | 
                   FE_DIVBYZERO | 
                   FE_OVERFLOW  | 
                   FE_UNDERFLOW);  
    signal(SIGFPE, catch_fpe);

    feraiseexcept(FE_DIVBYZERO);
}

Это не работает, как я ожидал. Выход i am in catch_fpe Также должно отображаться DIVBYZERO.

...