pastebin - collaborative debugging tool
rovema.kpaste.net RSS


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

  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.  
  26. static sigjmp_buf jmp_env;
  27. static volatile siginfo_t saved_siginfo;
  28.  
  29.  
  30. static void sigfpe_handler(int num, siginfo_t *info, void *ucontext)
  31. {
  32.         (void)num;
  33.         (void)ucontext;
  34.  
  35.         (void)feclearexcept(FE_ALL_EXCEPT);
  36.         (void)memcpy((void *)&saved_siginfo, info, sizeof(saved_siginfo));
  37.  
  38. #if 1
  39.         siglongjmp(jmp_env, 1);
  40. #else
  41.         throw std::invalid_argument( "you violated the fp math rules" );
  42. #endif
  43. }
  44.  
  45.  
  46. #define DEFINE_SIGFPE_TESTCASE_FUNC(f) .func = f , .funcstr = #f ,
  47. struct sigfpe_testcase
  48. {
  49.         const char *name;
  50.         const char *resultstr;
  51.         int result_si_code;
  52.         const std::function<void()> func;
  53.         const char *funcstr; /* function in ASCII form */
  54. };
  55.  
  56.  
  57. static
  58. const char *sigfpe_si_code_to_str(int si_code)
  59. {
  60.         switch(si_code)
  61.         {
  62.                 case FPE_INTDIV: return "FPE_INTDIV";
  63.                 case FPE_INTOVF: return "FPE_INTOVF";
  64.                 case FPE_FLTDIV: return "FPE_FLTDIV";
  65.                 case FPE_FLTOVF: return "FPE_FLTOVF";
  66.                 case FPE_FLTUND: return "FPE_FLTUND";
  67.                 case FPE_FLTRES: return "FPE_FLTRES";
  68.                 case FPE_FLTINV: return "FPE_FLTINV";
  69.                 case FPE_FLTSUB: return "FPE_FLTSUB";
  70.                 case FPE_FLTUNK: return "FPE_FLTUNK";
  71.                 case FPE_CONDTRAP: return "FPE_CONDTRAP";
  72.         }
  73.         return "unknown_fpe_code";
  74. }
  75.  
  76.  
  77.  
  78. static
  79. void run_single_test(sigfpe_testcase *test)
  80. {
  81.         struct sigaction action;
  82.         int ret;
  83.  
  84.         (void)memset(&action, 0, sizeof(action));
  85.  
  86.         action.sa_sigaction = sigfpe_handler;
  87.         (void)sigemptyset(&action.sa_mask);
  88.         action.sa_flags = SA_SIGINFO;
  89.         (void)sigaction(SIGFPE, &action, NULL);
  90.  
  91.         ret = feenableexcept(
  92.                 FE_INVALID   |
  93.                 FE_DIVBYZERO |
  94.                 FE_OVERFLOW  |
  95.                 FE_UNDERFLOW |
  96.                 FE_INEXACT);
  97.         if (ret)
  98.                 (void)printf("feenableexcept() failed: %x\n", ret);    
  99.        
  100.         try
  101.         {
  102.                 (void)memset((void *)&saved_siginfo, 0, sizeof(saved_siginfo));
  103.                
  104.                 ret = sigsetjmp(jmp_env, 1);
  105.                 if (ret) {
  106.                         (void)printf("#got_signal, %s/%d\n", sigfpe_si_code_to_str(saved_siginfo.si_code), (int)saved_siginfo.si_code);
  107.                 }
  108.                 else
  109.                 {
  110.                         (void)printf("#begin_math = '%s'\n", test->funcstr);
  111.  
  112.                         test->func();
  113.  
  114.                         (void)puts("#end_math");
  115.                 }
  116.         }
  117.         catch( const std::invalid_argument &e )
  118.         {
  119.                 std::cout << std::string("#got_exception '") + e.what() + "' \n";
  120.         }
  121. }
  122.  
  123.  
  124. static
  125. void runtest(void)
  126. {
  127.         struct sigfpe_testcase tests[] = {
  128.                 {
  129.                         .name = "intdevzero1",
  130.                         .resultstr = "intdiv",
  131.                         .result_si_code = FPE_INTDIV,
  132.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ int i=1,j=0; i = i/j; (void)i; }) )
  133.                 },
  134.                 {
  135.                         .name = "underflow1",
  136.                         .resultstr = "underflow",
  137.                         .result_si_code = FPE_FLTUND,
  138.                         DEFINE_SIGFPE_TESTCASE_FUNC( [=](void){ (void)exp(-708.5); } )
  139.                 },
  140.                 {
  141.                         .name = "overflow1",
  142.                         .resultstr = "overflow",
  143.                         .result_si_code = FPE_FLTOVF,
  144.                         DEFINE_SIGFPE_TESTCASE_FUNC( [=](void){ (void)expf(88.8); } )
  145.                 },
  146.                 {
  147.                         .name = "inexact1",
  148.                         .resultstr = "inexact",
  149.                         .result_si_code = FPE_FLTRES,
  150.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ double a=DBL_MAX,b=1,c; c=a+b; (void)c; }) )
  151.                 },
  152.         };
  153.        
  154.         for(int i = 0 ; i < 4 ; i++)
  155.         {
  156.                 run_single_test(&tests[i]);
  157.         }
  158. }
  159.  
  160.  
  161. int main(int ac, char *av[])
  162. {
  163.         (void)puts("#start.");
  164.  
  165.         runtest();
  166.  
  167.         (void)puts("#end.");
  168.         return EXIT_SUCCESS;
  169. }

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