How to raise different floating point exceptions in C?

433 views Asked by At

I am interested in raising floating point exceptions like Division by zero, Overflow, Underflow, etc.

I think what i am trying to do is possible if we can change the default behavior of trap when floating point exception occurs.

I am using functions in fenv.h. First, i enable the interrupt using feenableexcept and then i raise an exception using feraiseexcept.

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


int main(void) {
    feenableexcept(FE_UNDERFLOW);

    feraiseexcept(FE_OVERFLOW);

    return 0;
}

The message displayed in terminal is

Floating point exception (core dumped)

Instead of this, i want the message of this form

Overflow

I also tried handling SIGFPE. Since for every floating point exception, same signal SIGPE is raised, it does not help in differentiating different causes of signal. There is a similar question on Stack overflow which does not have any satisfactory answer.

We can use fetestexcept(FE_OVERFLOW) but that has to be expicitly written after every floating point operation to check for overflow.

Note: I compile my program using

gcc test_float -lm

edit:

I tried catching SIGFPE and wrote this program

#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);
}

It is not working as i expected. The output is i am in catch_fpe It should also have displayed DIVBYZERO.

0

There are 0 answers