pastebin - collaborative debugging tool
rovema.kpaste.net RSS


sig_fpu_trigger2.cpp
Posted by Anonymous on Fri 18th Feb 2022 13:25
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. extern "C"
  33. {
  34.         static void sigfpe_handler(int num, siginfo_t *info, void *ucontext)
  35.         {
  36.                 (void)num;
  37.                 (void)ucontext;
  38.  
  39.                 (void)feclearexcept(FE_ALL_EXCEPT);
  40.                 (void)memcpy((void *)&saved_siginfo, info, sizeof(saved_siginfo));
  41.  
  42.                 siglongjmp(jmp_env, 1);
  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. #ifdef FPE_FLTUNK
  71.                 case FPE_FLTUNK: return "FPE_FLTUNK";
  72. #endif /* FPE_FLTUNK */
  73. #ifdef FPE_CONDTRAP
  74.                 case FPE_CONDTRAP: return "FPE_CONDTRAP";
  75. #endif /* FPE_CONDTRAP */
  76.         }
  77.         return "unknown_fpe_code";
  78. }
  79.  
  80.  
  81.  
  82. static
  83. void run_single_test(const struct sigfpe_testcase *test)
  84. {
  85.         struct sigaction action;
  86.         int ret;
  87.  
  88.         (void)memset(&action, 0, sizeof(action));
  89.  
  90.         action.sa_sigaction = sigfpe_handler;
  91.         (void)sigemptyset(&action.sa_mask);
  92.         action.sa_flags = SA_SIGINFO;
  93.         (void)sigaction(SIGFPE, &action, NULL);
  94.  
  95.         ret = feenableexcept(
  96.                 FE_INVALID   |
  97.                 FE_DIVBYZERO |
  98.                 FE_OVERFLOW  |
  99.                 FE_UNDERFLOW |
  100.                 FE_INEXACT);
  101.         if (ret)
  102.                 (void)printf("feenableexcept() failed: %x\n", ret);    
  103.        
  104.         try
  105.         {
  106.                 (void)memset((void *)&saved_siginfo, 0, sizeof(saved_siginfo));
  107.                
  108.                 ret = sigsetjmp(jmp_env, 1);
  109.                 if (ret) {
  110.                         (void)printf("#got_signal, %s/%d\n",
  111.                                 sigfpe_si_code_to_str(saved_siginfo.si_code),
  112.                                 (int)saved_siginfo.si_code);
  113.                 }
  114.                 else
  115.                 {
  116.                         (void)printf("#begin_math = name='%s' / '%s'\n",
  117.                                 test->name,
  118.                                 test->funcstr);
  119.  
  120.                         test->func();
  121.  
  122.                         (void)puts("#end_math");
  123.                 }
  124.         }
  125.         catch( const std::invalid_argument &e )
  126.         {
  127.                 std::cout << std::string("#got_exception '") + e.what() + "' \n";
  128.         }
  129. }
  130.  
  131.  
  132. static
  133. void runtest(void)
  134. {
  135.         const struct sigfpe_testcase tests[] = {
  136.                 {
  137.                         .name = "intdevzero1",
  138.                         .resultstr = "intdiv",
  139.                         .result_si_code = FPE_INTDIV,
  140.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ int i=1,j=0; i = i/j; (void)i; }) )
  141.                 },
  142.                 {
  143.                         .name = "floatdevzero1",
  144.                         .resultstr = "intdiv",
  145.                         .result_si_code = FPE_FLTDIV,
  146.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ long double i=1.,j=0.; i = i/j; (void)i; }) )
  147.                 },
  148.                 {
  149.                         .name = "underflow1",
  150.                         .resultstr = "underflow",
  151.                         .result_si_code = FPE_FLTUND,
  152.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ double x = -708.5 ; (void)exp(x); }) )
  153.                 },
  154.                 {
  155.                         .name = "underflow2",
  156.                         .resultstr = "underflow",
  157.                         .result_si_code = FPE_FLTUND,
  158.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ (void)nextafterf(FLT_MIN, -INFINITY); }) )
  159.                 },
  160.                 {
  161.                         .name = "overflow1",
  162.                         .resultstr = "overflow",
  163.                         .result_si_code = FPE_FLTOVF,
  164.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ float x = 88.8f; (void)expf(x); }) )
  165.                 },
  166.                 {
  167.                         .name = "inexact1",
  168.                         .resultstr = "inexact",
  169.                         .result_si_code = FPE_FLTRES,
  170.                         DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ double a=DBL_MAX,b=1,c; c=a+b; (void)c; }) )
  171.                 },
  172.         };
  173.        
  174.         for(size_t i = 0 ; i < numelementsinarray(tests) ; i++)
  175.         {
  176.                 run_single_test(&tests[i]);
  177.         }
  178. }
  179.  
  180.  
  181. int main(int ac, char *av[])
  182. {
  183.         (void)puts("#start.");
  184.  
  185.         runtest();
  186.  
  187.         (void)puts("#end.");
  188.         return EXIT_SUCCESS;
  189. }

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