By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
426,248 Members | 1,979 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 426,248 IT Pros & Developers. It's quick & easy.

How to raise different floating point exceptions in C?

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

I am using functions in fenv.h and signal handling. Whenever, any floating point exception occurs,

The problem seems like when inside the function catch_fpe ,the flags set by feraiseexcept somehow gets cleared and no condition is true.

There is a similar question on bytes.com in which signal has to be raised explicitly by calling signal function.


Expand|Select|Wrap|Line Numbers
  1. #define _GNU_SOURCE
  2. #include <fenv.h>
  3. #include <stdio.h> 
  4. #include <signal.h>
  5. #include <stdlib.h>
  6.  
  7. void catch_fpe (int sig) {   
  8.  
  9.     //#pragma STDC FENV_ACCESS ON
  10.     printf("i am in catch_fpe\n");
  11.     if(fetestexcept(FE_OVERFLOW))
  12.         printf("OVERFLOW\n");
  13.     else if(fetestexcept(FE_UNDERFLOW))
  14.         printf("UNDERFLOW\n");
  15.     else if(fetestexcept(FE_DIVBYZERO))
  16.         printf("DIVBYZERO\n");
  17.     else if(fetestexcept(FE_INVALID))
  18.         printf("INVALID OPERATION\n");
  19.     else if(fetestexcept(FE_INEXACT))
  20.         printf("INEXACT RESULT\n");
  21.  
  22.     exit(0);
  23. }
  24.  
  25. int main()
  26. {
  27.     feclearexcept(FE_ALL_EXCEPT);
  28.     feenableexcept(FE_INVALID   | 
  29.                    FE_DIVBYZERO | 
  30.                    FE_OVERFLOW  | 
  31.                    FE_UNDERFLOW);  
  32.     signal(SIGFPE, catch_fpe);
  33.  
  34.     feraiseexcept(FE_DIVBYZERO);
  35. }
3 Weeks Ago #1

✓ answered by donbock

An online gcc manual refers to a command line switch to enable exception handling:

-fexceptions
Enable exception handling. Generates extra code needed to propagate exceptions. For some targets, this implies GCC generates frame unwind information for all functions, which can produce significant data size overhead, although it does not affect execution. If you do not specify this option, GCC enables it by default for languages like C++ that normally require exception handling, and disables it for languages like C that do not normally require it. However, you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++. You may also wish to disable this option if you are compiling older C++ programs that don’t use exception handling.

Share this Question
Share on Google+
5 Replies


Expert 100+
P: 2,398
1. Line 9 is commented out. You need to turn on FENV_ACCESS for fetestexcept() to work. If this pragma isn’t supported by your compiler then you should wonder if fenv.h is fully supported.

2. Line 9: I don’t know if it matters, but I’m used to seeing “on” instead of “ON” in the pragma.

3. Replace lines 11-20 with something like this:
Expand|Select|Wrap|Line Numbers
  1. int fe;
  2. fe = fetestexcept(FE_ALL_EXCEPT);
  3. if (fe & FE_OVERFLOW) printf(“Overflow\n”);
  4. ...
Do these changes make a difference for you?
3 Weeks Ago #2

P: 4
Thanks for the reply @donbock.

Changes you suggested do not change the output.

Is FENV_ACCESS at the right place?

Maybe this behavior is due to deprecated signal() function. I will try using sigaction.
3 Weeks Ago #3

P: 4
I tried using sigaction but the output remains same.

Expand|Select|Wrap|Line Numbers
  1. #define _GNU_SOURCE
  2. #include <fenv.h>
  3. #include <stdio.h> 
  4. #include <signal.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. #pragma STDC FENV_ACCESS on
  9.  
  10. void hdl(int sig, siginfo_t *siginfo, void *context)
  11. {
  12.     int fe;
  13.     fe = fetestexcept(FE_ALL_EXCEPT);
  14.  
  15.     printf("i am in catch_fpe\n");
  16.  
  17.     if( fe & FE_OVERFLOW)
  18.         printf("OVERFLOW\n");
  19.     else if(fe & FE_UNDERFLOW)
  20.         printf("UNDERFLOW\n");
  21.     else if(fe & FE_DIVBYZERO)
  22.         printf("DIVBYZERO\n");
  23.     else if(fe & FE_INVALID)
  24.         printf("INVALID OPERATION\n");
  25.     else if(fe & FE_INEXACT)
  26.         printf("INEXACT RESULT\n");
  27.  
  28.     exit(0);
  29. }
  30.  
  31. int main()
  32. {
  33.  
  34.     struct sigaction new_action;
  35.     memset(&new_action, '\0', sizeof(new_action));
  36.      new_action.sa_sigaction = &hdl;
  37.     new_action.sa_flags = SA_SIGINFO;
  38.     sigaction (SIGFPE, &new_action, NULL);
  39.  
  40.     feclearexcept(FE_ALL_EXCEPT);
  41.     feenableexcept(FE_INVALID   | 
  42.                    FE_DIVBYZERO | 
  43.                    FE_OVERFLOW  | 
  44.                    FE_UNDERFLOW);  
  45.  
  46.     // signal(SIGFPE, catch_fpe);
  47.  
  48.     feraiseexcept(FE_DIVBYZERO);
  49.  
  50. }
  51.  
  52.  
3 Weeks Ago #4

Expert 100+
P: 2,398
An online gcc manual refers to a command line switch to enable exception handling:

-fexceptions
Enable exception handling. Generates extra code needed to propagate exceptions. For some targets, this implies GCC generates frame unwind information for all functions, which can produce significant data size overhead, although it does not affect execution. If you do not specify this option, GCC enables it by default for languages like C++ that normally require exception handling, and disables it for languages like C that do not normally require it. However, you may need to enable this option when compiling C code that needs to interoperate properly with exception handlers written in C++. You may also wish to disable this option if you are compiling older C++ programs that don’t use exception handling.
3 Weeks Ago #5

P: 4
Thanks for having a look.
I tried using this switch. It does not affect the output.
3 Weeks Ago #6

Post your reply

Sign in to post your reply or Sign up for a free account.