1

Environment Windows 10 with MSVC2015 professional, compile with /EHa

What I'm doing: enabling floating point exception to be able to catch exceptions when some bad things happen, just for debuging

code:

namespace debug_details
{
void (*defaultStructuredExceptionFunc)(unsigned int, PEXCEPTION_POINTERS) = nullptr;

void my_trans_func(unsigned int exceptionCode, PEXCEPTION_POINTERS pExpInfo)
{
    switch (exceptionCode)
    {
    case EXCEPTION_FLT_DENORMAL_OPERAND:
    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_INEXACT_RESULT:
    case EXCEPTION_FLT_INVALID_OPERATION:
    case EXCEPTION_FLT_OVERFLOW:
    case EXCEPTION_FLT_STACK_CHECK:
    case EXCEPTION_FLT_UNDERFLOW:
    {
        _clearfp();
        std::stringstream ss;
        ss << "floating-point structured exception: 0x" << std::hex << exceptionCode;
        throw std::runtime_error(ss.str());
    }
    default:
        if (defaultStructuredExceptionFunc != nullptr)
        {
            defaultStructuredExceptionFunc(exceptionCode, pExpInfo);
        }
    };
};

void EnableFloatingPointExceptions()
{
    unsigned int fe_value = ~(/*_EM_INVALID | _EM_DENORMAL |*/ _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW /* | _EM_INEXACT*/);
    unsigned int mask = _MCW_EM;
    unsigned int currentWord = 0;
    _clearfp();
    errno_t result = _controlfp_s(&currentWord, fe_value, mask); // https://msdn.microsoft.com/en-us/library/c9676k6h.aspx
    DVASSERT(result == 0);
    debug_details::defaultStructuredExceptionFunc = _set_se_translator(&debug_details::my_trans_func); // https://msdn.microsoft.com/en-us/library/5z4bw5h5.aspx

    float32 div = 0.f;
    float32 f = 15.f / div;
    float32 f2 = 30.f * div;
}

} // end namespace debug_details

I expect EXCEPTION_FLT_DIVIDE_BY_ZERO, but have multiple floating point traps

Please help to understand what is going on? Thanks in advance!

leanid.chaika
  • 2,143
  • 2
  • 27
  • 30

2 Answers2

1

I found answer on MSDN, problem with x86 platform, on x64 we can get correct exception code from thread context register see ref - // https://social.msdn.microsoft.com/Forums/en-US/48f63378-19be-413f-88a5-0f24aa72d3c8/the-exceptions-statusfloatmultipletraps-and-statusfloatmultiplefaults-is-needed-in-more

leanid.chaika
  • 2,143
  • 2
  • 27
  • 30
-1

There are several things to know about FP exceptions:

  • controlfp's flags mask (i.e. disable) the exceptions you set, not enable them. So to enable only division by 0, you'd need set everything but in EM_ZERODIVIDE in the arguments
  • exceptions in SSE code are not affected by controlfp, you'd need to use _mm_setctr (so if you have SSE/AVX enabled in the compiler settings, most of your code will likely use SSE, even scalar)
  • if an exception happened when it was masked, it'll break if you enable it later (unless some code clears the status word)
Anton Knyazyev
  • 464
  • 4
  • 7