- /*
- * C++ SIGFPE handling demo
- *
- * Compile with:
- * $ g++ -std=gnu++17 -Wall lam1.cpp #
- * $ clang++ -std=gnu++17 -Wall lam1.cpp #
- *
- * Written by Roland Mainz <roland.mainz@nrubsig.org>
- */
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <setjmp.h>
- #include <signal.h>
- #include <math.h>
- #include <fenv.h>
- #include <limits.h>
- #include <stdexcept>
- #include <iostream>
- #include <cfloat>
- #include <functional>
- static sigjmp_buf jmp_env;
- static volatile siginfo_t saved_siginfo;
- static void sigfpe_handler(int num, siginfo_t *info, void *ucontext)
- {
- (void)num;
- (void)ucontext;
- (void)feclearexcept(FE_ALL_EXCEPT);
- (void)memcpy((void *)&saved_siginfo, info, sizeof(saved_siginfo));
- #if 1
- siglongjmp(jmp_env, 1);
- #else
- throw std::invalid_argument( "you violated the fp math rules" );
- #endif
- }
- #define DEFINE_SIGFPE_TESTCASE_FUNC(f) .func = f , .funcstr = #f ,
- struct sigfpe_testcase
- {
- const char *name;
- const char *resultstr;
- int result_si_code;
- const std::function<void()> func;
- const char *funcstr; /* function in ASCII form */
- };
- static
- const char *sigfpe_si_code_to_str(int si_code)
- {
- switch(si_code)
- {
- case FPE_INTDIV: return "FPE_INTDIV";
- case FPE_INTOVF: return "FPE_INTOVF";
- case FPE_FLTDIV: return "FPE_FLTDIV";
- case FPE_FLTOVF: return "FPE_FLTOVF";
- case FPE_FLTUND: return "FPE_FLTUND";
- case FPE_FLTRES: return "FPE_FLTRES";
- case FPE_FLTINV: return "FPE_FLTINV";
- case FPE_FLTSUB: return "FPE_FLTSUB";
- case FPE_FLTUNK: return "FPE_FLTUNK";
- case FPE_CONDTRAP: return "FPE_CONDTRAP";
- }
- return "unknown_fpe_code";
- }
- static
- void run_single_test(sigfpe_testcase *test)
- {
- struct sigaction action;
- int ret;
- (void)memset(&action, 0, sizeof(action));
- action.sa_sigaction = sigfpe_handler;
- (void)sigemptyset(&action.sa_mask);
- action.sa_flags = SA_SIGINFO;
- (void)sigaction(SIGFPE, &action, NULL);
- ret = feenableexcept(
- FE_INVALID |
- FE_DIVBYZERO |
- FE_OVERFLOW |
- FE_UNDERFLOW |
- FE_INEXACT);
- if (ret)
- (void)printf("feenableexcept() failed: %x\n", ret);
- try
- {
- (void)memset((void *)&saved_siginfo, 0, sizeof(saved_siginfo));
- ret = sigsetjmp(jmp_env, 1);
- if (ret) {
- (void)printf("#got_signal, %s/%d\n", sigfpe_si_code_to_str(saved_siginfo.si_code), (int)saved_siginfo.si_code);
- }
- else
- {
- (void)printf("#begin_math = '%s'\n", test->funcstr);
- test->func();
- (void)puts("#end_math");
- }
- }
- catch( const std::invalid_argument &e )
- {
- std::cout << std::string("#got_exception '") + e.what() + "' \n";
- }
- }
- static
- void runtest(void)
- {
- struct sigfpe_testcase tests[] = {
- {
- .name = "intdevzero1",
- .resultstr = "intdiv",
- .result_si_code = FPE_INTDIV,
- DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ int i=1,j=0; i = i/j; (void)i; }) )
- },
- {
- .name = "underflow1",
- .resultstr = "underflow",
- .result_si_code = FPE_FLTUND,
- DEFINE_SIGFPE_TESTCASE_FUNC( [=](void){ (void)exp(-708.5); } )
- },
- {
- .name = "overflow1",
- .resultstr = "overflow",
- .result_si_code = FPE_FLTOVF,
- DEFINE_SIGFPE_TESTCASE_FUNC( [=](void){ (void)expf(88.8); } )
- },
- {
- .name = "inexact1",
- .resultstr = "inexact",
- .result_si_code = FPE_FLTRES,
- DEFINE_SIGFPE_TESTCASE_FUNC( ([=](void){ double a=DBL_MAX,b=1,c; c=a+b; (void)c; }) )
- },
- };
- for(int i = 0 ; i < 4 ; i++)
- {
- run_single_test(&tests[i]);
- }
- }
- int main(int ac, char *av[])
- {
- (void)puts("#start.");
- runtest();
- (void)puts("#end.");
- return EXIT_SUCCESS;
- }
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
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.