0

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.

FrackeR011
  • 61
  • 10
  • Note `feenableexcept()` is not part the standard C library. What compiler, options are you using? Ah, i see `_GNU_SOURCE` - tag added. – chux - Reinstate Monica Jun 27 '19 at 03:41
  • I am linking with maths library. – FrackeR011 Jun 27 '19 at 03:41
  • For most CPUs, you don't need anything after every floating point operation - the CPU automatically sets flags in a control/status register after every floating point instruction, realizes the exception is unmasked, and triggers an interrupt/exception that the kernel handles (by converting it into a signal). Then your signal handler starts and `fetestexcept()` can examine the contents of the flags in a floating point control/status register (that the CPU set initially). Note: "most CPUs" is not all CPUs (e.g. it won't work like that for RISC-v). – Brendan Jun 27 '19 at 05:34
  • @Brendan i think i tried what you said. My signal handler is not able to correctly determine the status of flag. – FrackeR011 Jun 27 '19 at 06:41
  • @FrackeR011: This looks like it might help: https://bytes.com/topic/c/answers/703408-fetestexcept-fails – Brendan Jun 27 '19 at 08:37
  • @Brendan Unfortunately, it does work but not as i wanted. In it, exceptions are raised explicitly by calling fperror(0). SIGFPE should be raised automatically. We i use feenableexpect, previous floating point environment somehow gets cleared. – FrackeR011 Jun 27 '19 at 09:55

0 Answers0