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:
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 value0x80003
, but by the time I get to where the divide-by-zero occurs, the value is0x80013
. At this time the_status87()
is returning a value of0x1
. My theory is that some other floating-point event (such asEXCEPTION_FLT_INEXACT_RESULT
) is setting the_status87
bit, but it is not firing the exception due to the mask I used?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.