Floating point processing with floating point exceptions enabled

I am having a problem with floating point exceptions included in Visual Studio 2005. If I have code like this:

double d = 0.0; double d2 = 3.0; double d3 = d2/d; 

and if I register the SEH handler procedure, then I can easily turn the div-by-zero into a C ++ exception and catch it. So far so good.

However, when I do this, the first operand (0.0 in the above example) remains on the FPU register stack. If I do this eight times, then I will start to receive a floating point stack check exception with EVERY floating point operation from now on.

I can handle this by using the __asm ​​block to execute FSTP, thereby popping the rejected value from the stack, and that's all right.

However, this bothers me because I have not seen this discussed elsewhere . How can I be sure of the number of values ​​that I should pop up? Is it safe to just pop up everything on the stack during the exception? Are there any recommended best practices in this area?

Thanks!

+6
c ++ floating-point exception visual-c ++
source share
1 answer

While I cannot find anything, I can give some explanation regarding the likely answer:

The ABI determines that when the function is called, the stack must be empty, and it must be empty again on exit if the return is not a floating-point value, where it will be the only element on the stack.

Since the exception handler should be able to return to any place, some criteria must be met at these places. The question here is whether the stack spread has any knowledge of the FPU stack of a function having catch ()? Most likely, the answer is no, because it’s easier and faster to create a suitable return point with fixed properties than to include a full FPU stack in unwinding.

What leads to your problem is usually an exception when the compiler takes care that the FPU is empty, but in the SEH handler the compiler has no idea that he called the write to another function and therefore cannot take care of things just in case. (except he's terribly slow again)

This means that most likely the FPU stack should be in a “consistent” state after returning, which means that you probably want to get the equivalent of an EMMS instruction.

Why EMMS? Well, if it is not supported, it does the following:

  • clear stack (which fixes all remaining floating point arguments)
  • clears stack tags (which captures an unused stack when exiting a function with MMX support)

If you want to support Pentium 1 or worse, you can of course () around EMMS and use something else instead.

There are no guarantees, of course, but I hope I explained why the likely answer is enough.

+3
source share

All Articles