2

I am attempting to catch floating point exceptions in code compiled using Visual Studio 2008, similar to this post: Visual C++ / Weird behavior after enabling floating-point exceptions (compiler bug ?)

Just when I thought I had it working great and divide-by-zero's being caught and printed to the command line, I realized there are certain cases that were not getting caught. The divide-by-zero (or other numeric excpetion) seems to be caught ONLY if it was the first floating point exception to occur. I've attempted to disable other exceptions such as EXCEPTION_FLT_INEXACT_RESULT (really? isn't that the point of floating point?)

Anyway, here's my attempt at setting up the floating point register and the SEH, with some instrumentation for debug:

    unsigned int cw;
    unsigned int ret;
    unsigned int stat1;
    unsigned int stat2;

    stat1 = _status87();
    cw = _MCW_EM  & ~_EM_INEXACT & ~_EM_UNDERFLOW &  ~_EM_DENORMAL;
    ret = _control87(0,cw);
    stat2 = _status87();

    printf("_status87() returns: 0x%x!\n",stat1);
    printf("calling _control87 with inputs (0 , 0x%x)\n",cw);
    printf("_control87() returned: 0x%x!\n",ret);
    printf("_status87() returns: 0x%x!\n",stat2);

    /*Setup the exception filter */
    SetUnhandledExceptionFilter(fsim_stuff_windows_filter_function);

At the beginning of my program, this code prints:

_status87() returns: 0x1!
calling _control87 with inputs (0 , 0x1c)
_control87() returned: 0x80003!
_status87() returns: 0x0!

And yay verily if I put in a divide-by-zero, I see my fsim_stuff_windows_filter_function gets called with a EXCEPTION_FLT_DIVIDE_BY_ZERO

However, in another case a divide-by-zero was slipping by. I instrumented the code just prior to the divide by zero to inspect the situation:

unsigned int ret1;
unsigned int stat1;

stat1 = _status87();
ret1 = _control87(0,0);

printf("_status87() returns: 0x%x!\n",stat1);
printf("_control87(0,0) returned: 0x%x!\n",ret1);

In my application, this code prints (I've also included the result of the divide-by-zero assignment to foo here):

_status87() returns: 0x1!
calling _control87(0,0) returned:0x80013!
foo = -1.#IND00!

Here the exception never was fired. I tried one more step, which was to re-assert _control_fp just prior to the divide by zero, exactly the same way done at initialization. Here's the resulting print, again this is just before the divide by zero:

_status87() returns: 0x1!
calling _control87 with inputs (0 , 0)
_control87(0,0) returned: 0x80013!
_control87(0,0x1c) returned: 0x80003!
_status87() returns: 0x0!
FPSTUFF: EXCEPTION_FLT_INVALID_OPERATION

Here we can see that the exception did indeed file, although curiously this time with an ID of EXCEPTION_FLT_INVALID_OPERATION as opposed to EXCEPTION_FLT_DIVIDE_BY_ZERO

After all that, I have a few questions:

  1. Any thoughts on why the return value from _control87 would change after initialization? I'm certain that it is not called other places in the code. The result of initialization returned the value 0x80003, but by the time I get to where the divide-by-zero occurs, the value is 0x80013. At this time the _status87() is returning a value of 0x1. My theory is that some other floating-point event (such as EXCEPTION_FLT_INEXACT_RESULT) is setting the _status87 bit, but it is not firing the exception due to the mask I used?

  2. Should it be necessary to re-assert _control87? I tried setting ALL the bits in the _control87 flag, then clearing _status87 for exceptions that I didn't care about. However this caused an endless loop. The code would return to the place that the exception occurred, and re-fire the exception over and over again.

Thanks in advance for any advice or insight shared.

Bodo
  • 9,287
  • 1
  • 13
  • 29
jHops
  • 340
  • 1
  • 3
  • 11
  • 2
    Large amounts of description but no [mcve]. Where's the arithmetic? How do we know it isn't evaluated at compile time? – David Heffernan Jan 26 '16 at 22:44
  • Hi David - I left out the actual arithmetic as it didn't seem important compared to setting up the exception handling and floating point register. The line in question looks something like: – jHops Jan 27 '16 at 13:23
  • Let me try that again: Hi David - I left out the actual arithmetic as it didn't seem important compared to setting up the exception handling and floating point register. The line in question looks something like:`foo = (((b - d) * 6.0 * tValid - g1 * ch) * z + ((x * -t + x ) + z * ch)) / ((4.0 * omega * b - 3.0 * b) * t + ch * ch);`. All variables are doubles. In this instance, omega, b, and ch were all zero. All of these variables are inputs to the function so the compiler would not be able to evaluate at compile time. – jHops Jan 27 '16 at 13:38
  • Let me try again. Please show a [mcve]. – David Heffernan Jan 27 '16 at 14:46

0 Answers0