Допустим, вы решили обрабатывать у себя в программе исключения, которые могут генерироваться при операциях с плавающей запятой. Это можно сделать в обычном C коде и механизм исключений из С++ не нужен. В данной заметке я приведу код для воспроизведения пяти ошибок и их обработки в ОС linux.
#define PRINTF (void)printf #include <stdio.h> #include <stdlib.h> #include <math.h> #pragma STDC FENV_ACCESS ON #include <fenv.h> int main (void); static void handle_exc(int mask); int add_floats(float a, float b, float* result); int main() { double inf; float zero, one; float result; zero = 0.0; inf = 1.0; inf = inf/zero; int fpeRaised; // we store flags in here /*----------------------------------------------------------------*/ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: result = inf*zero\n"); result = inf*zero; fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nInf = %g\tZero = %g\tInf*Zero = %g\n", inf, zero, result); /*----------------------------------------------------------------*/ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: result = one + inf*zero\n"); one = 1.0; result = one + inf*zero; fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nOne = %g\tInf = %g\tZero = %g\tOne + Inf*Zero = %g\n", one, inf, zero, result); /*----------------------------------------------------------------*/ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: result = inf + inf\n"); inf = one/zero; result = inf; feclearexcept(FE_ALL_EXCEPT); result = inf + inf; fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nInf = %g\tInf = %g\tInf + Inf = %g\n", inf, inf, result); /*----------------------------------------------------------------*/ feclearexcept(FE_ALL_EXCEPT); /* expect no exceptions here */ PRINTF("\n\nBegin test: result = 1. + 2.\n"); one = 1.0; float two = 2.2; result = one + two; fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nOne = %g\tTwo = %g\tOne + Two = %g\n", one, two, result); /*----------------------------------------------------------------*/ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: result = 0. / 0.\n"); result = zero/zero; fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nZero = %g\tZero = %g\tZero/Zero = %g\n", zero, zero, result); /*----------------------------------------------------------------*/ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: underflow\n"); double a = 1e-40; result = a; fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nResult = %g\n", result); /*----------------------------------------------------------------*/ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: sqrt for a negative number\n"); result = sqrt( -1.00 ); fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nsqrt for a negative value %g\n", result); /*----------------------------------------------------------------*/ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: result = 1. + HUGE\n"); one = 1.0; float huge = 1.0E100; result = one + huge; fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nOne = %g\tHuge = %g\tOne + Huge = %g\n", one, huge, result); /*----------------------------------------------------------------*/ /* Divide-by-zero operation */ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: division by zero\n"); result = one / zero; fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\ndivision by zero %g\n", result); /*----------------------------------------------------------------*/ /* overflow */ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: overflow\n"); result = expf(88.8); fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nOverflow %g\n", result); /*----------------------------------------------------------------*/ /*testing inexact*/ feclearexcept(FE_ALL_EXCEPT); PRINTF("\n\nBegin test: inexact\n"); double c = 0.1; c = sin(30) * a; fpeRaised = fetestexcept(FE_ALL_EXCEPT); //PRINTF("%d\n", fpeRaised); handle_exc(fpeRaised); PRINTF("\nInexact, %g \n", c); /*----------------------------------------------------------------*/ PRINTF("\n\nBegin test: add function\n"); fpeRaised = add_floats(3., one, &result); handle_exc(fpeRaised); PRINTF("\ntesting add function, %g \n", result); PRINTF("\n\nEnd tests\n"); return (EXIT_SUCCESS); } int add_floats(float a, float b, float* result){ feclearexcept(FE_ALL_EXCEPT); *result = a + b; int fpeRaised = fetestexcept(FE_ALL_EXCEPT); return fpeRaised; } static void handle_exc(int mask){ if (mask & FE_INVALID) PRINTF(" FP_INVALID_OPERATION "); if (mask & FE_DIVBYZERO) PRINTF(" FP_ZERO_DIVIDE "); if (mask & FE_OVERFLOW) PRINTF(" FP_OVERFLOW "); if (mask & FE_UNDERFLOW) PRINTF(" FP_UNDERFLOW "); if (mask & FE_INEXACT) PRINTF(" FP_INEXACT "); } |