pastebin - collaborative debugging tool
rovema.kpaste.net RSS


sig_fpu_trigger2.cpp
Posted by Anonymous on Mon 14th Feb 2022 18:15
raw | new post
view followups (newest first): sig_fpu_trigger2.cpp by Anonymous
modification of post by Anonymous (view diff)

  1. /*
  2.  * C++ SIGFPE handling demo
  3.  *
  4.  * Compile with:
  5.  * $ g++ -std=gnu++17 -Wall lam1.cpp #
  6.  * $ clang++ -std=gnu++17 -Wall lam1.cpp #
  7.  *
  8.  * Written by Roland Mainz <roland.mainz@nrubsig.org>
  9.  */
  10.  
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <stdio.h>
  14. #include <setjmp.h>
  15. #include <signal.h>
  16. #include <math.h>
  17. #include <fenv.h>
  18. #include <limits.h>
  19.  
  20. #include <stdexcept>
  21. #include <iostream>
  22. #include <cfloat>
  23. #include <functional>
  24.  
  25. /* Number of elements in a C99/C++ array */
  26. #define numelementsinarray(ar) (sizeof(ar)/sizeof((ar)[0]))
  27.  
  28.  
  29. static sigjmp_buf jmp_env;
  30. static volatile siginfo_t saved_siginfo;
  31.  
  32.  
  33. static void sigfpe_handler(int num, siginfo_t *info, void *ucontext)
  34. {
  35.         (void)num;
  36.         (void)ucontext;
  37.  
  38.         (void)feclearexcept(FE_ALL_EXCEPT);
  39.         (void)memcpy((void *)&saved_siginfo, info, sizeof(saved_siginfo));
  40.  
  41. #if 1
  42.         siglongjmp(jmp_env, 1);
  43. #else
  44.         throw std::invalid_argument( "you violated the fp math rules" );
  45. #endif
  46. }
  47.  
  48.  
  49. #define DEFINE_SIGFPE_TESTCASE_FUNC(f) .func = f , .funcstr = #f ,
  50. struct sigfpe_testcase
  51. {
  52.         const char *name;
  53.         const char *resultstr;
  54.         int result_si_code;
  55.         const std::function<void(void)> func;
  56.         const char *funcstr; /* function in ASCII form */
  57. };
  58.  
  59.  
  60. static
  61. const char *sigfpe_si_code_to_str(int si_code)
  62. {
  63.         switch(si_code)
  64.         {
  65.                 case FPE_INTDIV: return "FPE_INTDIV";
  66.                 case FPE_INTOVF: return "FPE_INTOVF";
  67.                 case FPE_FLTDIV: return "FPE_FLTDIV";
  68.                 case FPE_FLTOVF: return "FPE_FLTOVF";
  69.                 case FPE_FLTUND: return "FPE_FLTUND";
  70.                 case FPE_FLTRES: return "FPE_FLTRES";
  71.                 case FPE_FLTINV: return "FPE_FLTINV";
  72.                 case FPE_FLTSUB: return "FPE_FLTSUB";
  73.                 case FPE_FLTUNK: return "FPE_FLTUNK";
  74.                 case FPE_CONDTRAP: return "FPE_CONDTRAP";
  75.         }
  76.         return "unknown_fpe_code";
  77. }
  78.  
  79.  
  80.  
  81. static
  82. void run_single_test(const struct sigfpe_testcase *test)
  83. {
  84.         struct sigaction action;
  85.         int ret;
  86.  
  87.         (void)memset(&action, 0, sizeof(action));
  88.  
  89.         action.sa_sigaction = sigfpe_handler;
  90.         (void)sigemptyset(&action.sa_mask);
  91.         action.sa_flags = SA_SIGINFO;
  92.         (void)sigaction(SIGFPE, &action, NULL);
  93.  
  94.         ret = feenableexcept(
  95.                 FE_INVALID   |
  96.                 FE_DIVBYZERO |
  97.                 FE_OVERFLOW  |
  98.                 FE_UNDERFLOW |
  99.                 FE_INEXACT);
  100.         if (ret)
  101.                 (void)printf("feenableexcept() failed: %x\n", ret);    
  102.        
  103.         try
  104.         {
  105.                 (void)memset((void *)&saved_siginfo, 0, sizeof(saved_siginfo));
  106.                
  107.                 ret = sigsetjmp(jmp_env, 1);
  108.                 if (ret) {
  109.                         (void)printf("#got_signal, %s/%d\n",
  110.                                 sigfpe_si_code_to_str(saved_siginfo.si_code),
  111.                                 (int)saved_siginfo.si_code);
  112.                 }
  113.                 else
  114.                 {
  115.                         (void)printf("#begin_math = name='%s' / '%s'\n",
  116.                                 test->name,
  117.                                 test->funcstr);
  118.  
  119.                         test->func();
  120.  
  121.                         (void)puts("#end_math");
  122.                 }
  123.         }
  124.         catch( const std::invalid_argument &e )
  125.         {
  126.                 std::cout << std::string("#got_exception '") + e.what() + "' \n";
  127.         }
  128. }
  129.  
  130.  
  131. static
  132. void runtest(void)
  133. {
  134.         const struct sigfpe_testcase tests[] = {
  135.                 {
  136.                         .name = "intdevzero1",
  137.                         .resultstr = "intdiv",
  138.                         .result_si_code = FPE_INTDIV,
  139.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ int i=1,j=0; i = i/j; (void)i; }) )
  140.                 },
  141.                 {
  142.                         .name = "floatdevzero1",
  143.                         .resultstr = "intdiv",
  144.                         .result_si_code = FPE_FLTDIV,
  145.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ long double i=1.,j=0.; i = i/j; (void)i; }) )
  146.                 },
  147.                 {
  148.                         .name = "underflow1",
  149.                         .resultstr = "underflow",
  150.                         .result_si_code = FPE_FLTUND,
  151.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ double x = -708.5 ; (void)exp(x); }) )
  152.                 },
  153.                 {
  154.                         .name = "underflow2",
  155.                         .resultstr = "underflow",
  156.                         .result_si_code = FPE_FLTUND,
  157.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ (void)nextafterf(FLT_MIN, -INFINITY); }) )
  158.                 },
  159.                 {
  160.                         .name = "overflow1",
  161.                         .resultstr = "overflow",
  162.                         .result_si_code = FPE_FLTOVF,
  163.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ float x = 88.8f; (void)expf(x); }) )
  164.                 },
  165.                 {
  166.                         .name = "inexact1",
  167.                         .resultstr = "inexact",
  168.                         .result_si_code = FPE_FLTRES,
  169.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ double a=DBL_MAX,b=1,c; c=a+b; (void)c; }) )
  170.                 },
  171.         };
  172.        
  173.         for(size_t i = 0 ; i < numelementsinarray(tests) ; i++)
  174.         {
  175.                 run_single_test(&tests[i]);
  176.         }
  177. }
  178.  
  179.  
  180. int main(int ac, char *av[])
  181. {
  182.         (void)puts("#start.");
  183.  
  184.         runtest();
  185.  
  186.         (void)puts("#end.");
  187.         return EXIT_SUCCESS;
  188. }

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at