pastebin - collaborative debugging tool
rovema.kpaste.net RSS


sig_fpu_trigger2.cpp
Posted by Anonymous on Mon 14th Feb 2022 15:50
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.  
  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(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",
  107.                                 sigfpe_si_code_to_str(saved_siginfo.si_code),
  108.                                 (int)saved_siginfo.si_code);
  109.                 }
  110.                 else
  111.                 {
  112.                         (void)printf("#begin_math = name='%s' / '%s'\n",
  113.                                 test->name,
  114.                                 test->funcstr);
  115.  
  116.                         test->func();
  117.  
  118.                         (void)puts("#end_math");
  119.                 }
  120.         }
  121.         catch( const std::invalid_argument &e )
  122.         {
  123.                 std::cout << std::string("#got_exception '") + e.what() + "' \n";
  124.         }
  125. }
  126.  
  127.  
  128. static
  129. void runtest(void)
  130. {
  131.         struct sigfpe_testcase tests[] = {
  132.                 {
  133.                         .name = "intdevzero1",
  134.                         .resultstr = "intdiv",
  135.                         .result_si_code = FPE_INTDIV,
  136.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ int i=1,j=0; i = i/j; (void)i; }) )
  137.                 },
  138.                 {
  139.                         .name = "underflow1",
  140.                         .resultstr = "underflow",
  141.                         .result_si_code = FPE_FLTUND,
  142.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ (void)exp(-708.5); }) )
  143.                 },
  144.                 {
  145.                         .name = "underflow2",
  146.                         .resultstr = "underflow",
  147.                         .result_si_code = FPE_FLTUND,
  148.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ (void)nextafterf(FLT_MIN, -INFINITY); }) )
  149.                 },
  150.                 {
  151.                         .name = "overflow1",
  152.                         .resultstr = "overflow",
  153.                         .result_si_code = FPE_FLTOVF,
  154.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ (void)expf(88.8); }) )
  155.                 },
  156.                 {
  157.                         .name = "inexact1",
  158.                         .resultstr = "inexact",
  159.                         .result_si_code = FPE_FLTRES,
  160.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ double a=DBL_MAX,b=1,c; c=a+b; (void)c; }) )
  161.                 },
  162.         };
  163.        
  164.         for(int i = 0 ; i < 5 ; i++)
  165.         {
  166.                 run_single_test(&tests[i]);
  167.         }
  168. }
  169.  
  170.  
  171. int main(int ac, char *av[])
  172. {
  173.         (void)puts("#start.");
  174.  
  175.         runtest();
  176.  
  177.         (void)puts("#end.");
  178.         return EXIT_SUCCESS;
  179. }

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