Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Floating-point division by zero also results in undefined behavior, although most implementations do not treat it as a terminal error. If additional precautions are not taken, it results in a silent error.

The most portable way of determining to determine if a floating-point exceptional condition has occurred is to use the floating-point exception facilities provided by C in fenv.h.

...

For information regarding floating-point number conversions, see FLP34-C. Ensure that floating-point conversions are within range of the new type.

The C standard does Standard does not require all implementations to support floating-point exceptions. Each exception macro in fenv.h is defined if, and only if, the corresponding exception is supported. Only implementations that use IEC 60559 (formerly IEEE-754) floating-point arithmetic are required to support all five exceptions defined by C (see the C Standard, section subclause 7.6.2 [ISO/IEC 9899:2011]). Nevertheless, these functions are the most portable solution for handling floating-point exceptions.

A less portable but potentially more secure solution is to use the capabilities provided by the underlying implementation. If this approach is taken, the caveats of that system need to must be well understood. The following table provides a starting point for some common operating systems:

...

Code Block
bgColor#FFCCCC
langc
void fpOper_noErrorChecking(void) {
  /* ... */
  double a = 1e-40, b, c = 0.1;
  float x = 0, y;
  /* inexactInexact and underflows */
  y = a;
  /* divideDivide by zero operation */
  b = y / x;
  /* inexactInexact (loss of precision) */
  c = sin(30) * a;
  /* ... */
}

...

Code Block
bgColor#ccccff
langc
#include <fenv.h>
#pragma STDC FENV_ACCESS ON

void fpOper_fenv(void) {
  double a = 1e-40, b, c = 0.1;
  float x = 0, y;
  int fpeRaised;
  /* ... */

  feclearexcept(FE_ALL_EXCEPT);
  /* Store a into y is inexact and underflows: */
  y = a;
  fpeRaised = fetestexcept(FE_ALL_EXCEPT);
  /* fpeRaised  has FE_INEXACT and FE_UNDERFLOW */

  feclearexcept(FE_ALL_EXCEPT);

  /* divideDivide by zero operation */
  b = y / x;
  fpeRaised = fetestexcept(FE_ALL_EXCEPT);
  /* fpeRaised has FE_DIVBYZERO */

  feclearexcept(FE_ALL_EXCEPT);

  c = sin(30) * a;
  fpeRaised = fetestexcept(FE_ALL_EXCEPT);
  /* fpeRaised has FE_INEXACT */

  feclearexcept(FE_ALL_EXCEPT);
  /* ... */
}

...

Microsoft Visual Studio 2008 and earlier versions do not support C functions to handle floating-point errors. Windows provides an alternative method for handling floating-point errors using _statusfp(), _statusfp2(), and _clearfp().

Code Block
bgColor#ccccff
langc
void fpOper_usingStatus(void) {
  /* ... */
  double a = 1e-40, b, c;
  float x = 0, y;
  unsigned int rv = _clearfp();

  /* Store into y is inexact and underflows: */
  y = a;
  rv = _clearfp();  /* rv has _SW_INEXACT and _SW_UNDERFLOW */

  /* zeroZero-divide */
  b = y / x; rv = _clearfp(); /* rv has _SW_ZERODIVIDE */

  /* inexactInexact */
  c = sin(30) * a; rv = _clearfp(); /* rv has _SW_INEXACT */
  /* ... */
}

...

Microsoft Visual Studio 2008 also uses structured exception handling (SEH) to handle floating-point operationoperations. SEH provides more information about the error and allows the programmer to change the results of the floating-point operation that caused the error condition.

Code Block
bgColor#ccccff
langc
void fp_usingSEH(void) {
  /* ... */
  double a = 1e-40, b, c = 0.1;
  float x = 0, y;
  unsigned int rv ;

  unmask_fpsr();

  _try {
    /* Store into y is inexact and underflows */
    y = a;

    /* divideDivide by zero operation */
    b = y / x;

    /* inexactInexact */
    c = sin(30) * a;
  }

  _except (_fpieee_flt(
             GetExceptionCode(),
             GetExceptionInformation(),
             fpieee_handler)) {
  {
  printf ("fpieee_handler: EXCEPTION_EXECUTE_HANDLER");
  }

  /* ... */
}

void unmask_fpsr(void) {
  unsigned int u;
  unsigned int control_word;
  _controlfp_s(&control_word, 0, 0);
  u = control_word & ~(_EM_INVALID
                     | _EM_DENORMAL
                     | _EM_ZERODIVIDE
                     | _EM_OVERFLOW
                     | _EM_UNDERFLOW
                     | _EM_INEXACT);
  _controlfp_s( &control_word, u, _MCW_EM);
  return ;
}

int fpieee_handler(_FPIEEE_RECORD *ieee) {
  /* ... */

  switch (ieee->RoundingMode) {
    case _FpRoundNearest:
      /* ... */
      break;

      /* Other RMs include _FpRoundMinusInfinity,
       * _FpRoundPlusInfinity, _FpRoundChopped */

      /* ... */
    }

  switch (ieee->Precision) {
    case _FpPrecision24:
      /* ... */
      break;

      /* Other Ps include _FpPrecision53*/
      /* ... */
    }

   switch (ieee->Operation) {
     case _FpCodeAdd:
       /* ... */
       break;

       /* Other Ops include _FpCodeSubtract, _FpCodeMultiply,
        * _FpCodeDivide, _FpCodeSquareRoot, _FpCodeCompare,
        * _FpCodeConvert, _FpCodeConvertTrunc */
       /* ... */
    }

  /* 
   * processProcess the bitmap ieee->Cause.
   * processProcess the bitmap ieee->Enable.
   * processProcess the bitmap ieee->Status.
   * processProcess the Operand ieee->Operand1, 
   * evaluate format and Value.
   * processProcess the Operand ieee->Operand2, 
   * evaluate format and Value.
   * processProcess the Result ieee->Result, 
   * evaluate format and Value .
   * The result should be set according to the operation 
   * specified in ieee->Cause and the result formatformatted as 
   * specified in ieee->Result.
   */

  /* ... */
}

...

Undetected floating-point errors may result in lower program efficiency, inaccurate results, or software vulnerabilities. Most processors stall for a significant duration (sometimes up to a second or even more on 32-bit desktop processors) when an operation incurs a NaN (not a number) value.

...

Tool

Version

Checker

Description

Compass/ROSE

 

 

Could detect violations of this rule by ensuring that floating-point operations are surrounded by feclearexcept() and fetestexcept(). It would need to look for type conversions to float or double, divisions (by a number not known to be nonzero), and multiplication. It may be wisest to apply this to all floating-point operations in general

PRQA QA-C
Include Page
PRQA_V
PRQA_V

4123
4124
4125
4126
4127
4128

Partially implemented

...

Bibliography

...