0
#include <iostream>
#include <float.h>
#pragma fenv_access (on)
int main(int, char**argv)
{
    unsigned int fp_control_word;
    _controlfp_s(&fp_control_word, 0, 0);
    const unsigned int new_fp_control_word = fp_control_word | _EM_INVALID | _EM_DENORMAL
        | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT;
    _controlfp_s(&fp_control_word, new_fp_control_word, _MCW_EM);
   try
   {    std::cout << std::atof(argv[1]) / std::atof(argv[2]) << std::endl;
   } catch (...)
   {    std::cout << "caught exception" << std::endl;
   }

}

I remember that it is possible to catch memory access errors on windows using a try-catch block.

There is already a question regarding this subject. But it is 10 years old and the code provided does not result in an exception, but in printing a NAN.

I was always curious about using this feature to abort some piece of numerical code in a nice way. The motivation is to abort some VERY COMPLEX piece of code immediately, if anywhere in this code a floating point exception occurred rather than keeping evaluating the rest of the code with NAN results -- which is rather slow and anyway does not make sense.

Please: I don't care if this is not supported by the C++ standard!

The question is, how to get this code to run into the catch-block -- e.g. by using the command line parameters 0.0 0.0!

For me it always prints out NAN.

What compiler options need to be used?

Or does the code need to be changed?

If one provokes a nullptr dereference in the try-block one will end up in the catch-block. But not for division by zero. One needs to use the compiler option /EHa to enable structured exception handling.

  • What is your question? Is it the title of your post? You use try/catch to catch floating point errors the same way you use try/catch to catch any sort of exception, assuming the floating point errors you're looking for are actually thrown exceptions. – Robert Harvey Nov 12 '20 at 16:00
  • 1
    Easy to see with the debugger, the new control word is the same as the old one. You want to *unmask* these exceptions, so use fp_control_word & ~(_EM_INVALID | _EM_DENORMAL ...). /EHa required, works fine. – Hans Passant Nov 12 '20 at 22:49

1 Answers1

2

Thanks to https://stackoverflow.com/users/17034/hans-passant for the solution.

Here comes the working code:

#include <iostream>
#include <float.h>
#pragma fenv_access (on)
int main(int, char**argv)
{
    unsigned int fp_control_word;
    _controlfp_s(&fp_control_word, 0, _MCW_EM);
    const unsigned int new_fp_control_word = fp_control_word & ~(_EM_INVALID
        | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT);
    _controlfp_s(&fp_control_word, new_fp_control_word, _MCW_EM);
    try
    {   std::cout << std::atof(argv[1]) / std::atof(argv[2]) << std::endl;
    } catch (...)
    {   std::cout << "caught exception" << std::endl;
    }
}