为什么在启用浮点exception之后,我得到了多个陷阱错误

环境Windows 10与MSVC2015专业,与/ EHa编译

我在做什么:启用浮点exception,以便能够在发生某些不良事件时捕获exception,仅用于debugging

码:

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 

我期望EXCEPTION_FLT_DIVIDE_BY_ZERO ,但是 多个浮点陷阱

请帮忙了解发生了什么事? 提前致谢!

Solutions Collecting From Web of "为什么在启用浮点exception之后,我得到了多个陷阱错误"

我找到了MSDN上的答案,与x86平台的问题,在x64上我们可以从线程上下文寄存器获得正确的异常代码请参阅 – https://social.msdn.microsoft.com/Forums/en-US/48f63378-19be- 413F-88a5-0f24aa72d3c8 /所述的例外-statusfloatmultipletraps和- statusfloatmultiplefaults-是需要的功能于更

有关FP异常有几件事要知道:

  • controlfp的标志掩码 (即禁用)您设置的例外,不启用它们。 因此,只能通过0启用除法,您需要在参数中设置 EM_ZERODIVIDE之外的所有内容
  • SSE代码中的异常不受controlfp的影响,您需要使用_mm_setctr(所以如果您在编译器设置中启用了SSE / AVX,则大部分代码可能会使用SSE,甚至是标量)
  • 如果一个异常发生在被屏蔽的时候,如果你稍后启用它将会中断(除非某些代码清除了状态字)