C++ 为什么启用浮点异常后,我遇到了多个陷阱错误
使用MSVC2015 professional的Windows 10环境,使用/EHa编译 我正在做的是:启用浮点异常,以便在发生一些不好的事情时捕获异常,只是为了调试 代码:C++ 为什么启用浮点异常后,我遇到了多个陷阱错误,c++,windows,math,visual-c++,C++,Windows,Math,Visual C++,使用MSVC2015 professional的Windows 10环境,使用/EHa编译 我正在做的是:启用浮点异常,以便在发生一些不好的事情时捕获异常,只是为了调试 代码: 命名空间调试\u详细信息 { void(*defaultStructuredExceptionFunc)(无符号int,PEXCEPTION_指针)=nullptr; void my_trans_func(无符号int exceptionCode,peexception_指针pExpInfo) { 开关(例外代码) {
命名空间调试\u详细信息
{
void(*defaultStructuredExceptionFunc)(无符号int,PEXCEPTION_指针)=nullptr;
void my_trans_func(无符号int exceptionCode,peexception_指针pExpInfo)
{
开关(例外代码)
{
大小写异常\u FLT\u非规范\u操作数:
案例例外情况除以零:
案例异常\u FLT\u不精确\u结果:
案例异常\u FLT\u无效\u操作:
案例异常\u FLT\u溢出:
案例异常\u FLT\u堆栈\u检查:
案例例外情况\u FLT\u下溢:
{
_clearfp();
std::stringstream-ss;
ss关于FP异常,有几点需要了解:
- controlfp的标志屏蔽(即禁用)您设置的异常,而不是启用它们。因此,要仅启用0除法,您需要在参数中设置除EM_ZERODIVIDE之外的所有内容
- SSE代码中的异常不受controlfp的影响,您需要使用_mm_setctr(因此,如果在编译器设置中启用了SSE/AVX,则大多数代码可能会使用SSE,甚至标量)
- 如果在屏蔽异常时发生异常,如果稍后启用它,异常将中断(除非某些代码清除状态字)
关于FP异常,有几点需要了解:
- controlfp的标志屏蔽(即禁用)您设置的异常,而不是启用它们。因此,要仅启用0除法,您需要在参数中设置除EM_ZERODIVIDE之外的所有内容
- SSE代码中的异常不受controlfp的影响,您需要使用_mm_setctr(因此,如果在编译器设置中启用了SSE/AVX,则大多数代码可能会使用SSE,甚至标量)
- 如果在屏蔽异常时发生异常,如果稍后启用它,异常将中断(除非某些代码清除状态字)
我在MSDN上找到了答案,x86平台有问题,在x64上我们可以从线程上下文寄存器中获得正确的异常代码请参阅ref-/我在MSDN上找到了答案,x86平台有问题,在x64上我们可以从线程上下文寄存器中获得正确的异常代码请参阅ref-/我在MSDN上找到了答案
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(¤tWord, 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