首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用SEH时,我如何解释GetExceptionCode结果?

在使用SEH时,我如何解释GetExceptionCode结果?
EN

Stack Overflow用户
提问于 2017-01-06 12:26:16
回答 2查看 1.3K关注 0票数 1

我一直试图写一些错误保护条款来识别dll中的问题,这是由第三方提供给我们的。此dll中可能存在问题(内存异常、浮点错误等),并且可以在不访问源代码的情况下识别这些错误。

我从各种SEH错误处理例程中收集了一些东西,但是尽管它能工作,但是有几个.和它不一致。我试着把每一个都隔离开来,然后对每一个人都提出一个问题。

这一项与GetExceptionCode有关,它在SEH _try/__except子句中用于标识错误。它似乎不那么可靠。

这是一个明显的除以零的案例:

代码语言:javascript
复制
#include <float.h>      // defines of _EM_OVERFLOW, etc.
#include <string.h>     // strncpy_s & strncat_s
#include <stdlib.h>     // malloc
#include <excpt.h>      // EXCEPTION_EXECUTE_HANDLER
#include <iostream>     // cout
#include <bitset>       // bitset
#include <conio.h>      // _kbhit
#pragma fenv_access (on)


const unsigned int SERIOUS_FP_EXCEPTIONS = _EM_DENORMAL | _EM_ZERODIVIDE | _EM_INVALID;
const unsigned int MINOR_FP_EXCEPTIONS = _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT;

int main(int argc, char[])
{
    double numerator = 1.0;
    double denominator = 0.0;
    double result = 0.0;

    unsigned int _previous_floating_point_control;
    _controlfp_s(&_previous_floating_point_control, 0, 0);
    _controlfp_s(nullptr, MINOR_FP_EXCEPTIONS, _MCW_EM);
    __try {
        result = numerator / denominator;
        _controlfp_s(NULL, _previous_floating_point_control, _MCW_EM);
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        std::cout << "_EM_INEXACT    = " << std::bitset<32>(_EM_INEXACT) << std::endl;
        std::cout << "_EM_UNDERFLOW  = " << std::bitset<32>(_EM_UNDERFLOW) << std::endl;
        std::cout << "_EM_OVERFLOW   = " << std::bitset<32>(_EM_OVERFLOW) << std::endl;
        std::cout << "_EM_ZERODIVIDE = " << std::bitset<32>(_EM_ZERODIVIDE) << std::endl;
        std::cout << "_EM_INVALID    = " << std::bitset<32>(_EM_INVALID) << std::endl;
        std::cout << "_EM_DENORMAL   = " << std::bitset<32>(_EM_DENORMAL) << std::endl;
        std::cout << "_EM_AMBIGUOUS  = " << std::bitset<32>(_EM_AMBIGUOUS) << std::endl;
        std::cout << std::endl;
        std::cout << "                                      divide-by-zero" << std::endl;
        std::cout << "                                             |" << std::endl;
        std::cout << "            ambiguous code?                underflow" << std::endl;
        std::cout << "                  |                          : |" << std::endl;
        std::cout << "                  v                          v v" << std::endl;
        std::cout << "Exception code = " << std::bitset<32>(GetExceptionCode()) << std::endl;
        std::cout << "                             ^              ^ ^ ^" << std::endl;
        std::cout << "                             |              : : |" << std::endl;
        std::cout << "                     denormal number     inexact number" << std::endl;
        std::cout << "                                            : |" << std::endl;
        std::cout << "                                          overflow" << std::endl;
        std::cout << "                                            |" << std::endl;
        std::cout << "                                     invalid number" << std::endl;

        if (GetExceptionCode() & _EM_ZERODIVIDE)
            std::cout << "ERROR! Divide By Zero!" << std::endl;
        else
            std::cout << "No divide by zero found here!" << std::endl;
        _controlfp_s(NULL, _previous_floating_point_control, _MCW_EM);
    }

    std::cout << "result = " << result << std::endl;

    while (!_kbhit())   // Wait until a key is pressed to close console.
    { }
}

这张照片印的是:

代码语言:javascript
复制
_EM_INEXACT    = 00000000000000000000000000000001
_EM_UNDERFLOW  = 00000000000000000000000000000010
_EM_OVERFLOW   = 00000000000000000000000000000100
_EM_ZERODIVIDE = 00000000000000000000000000001000
_EM_INVALID    = 00000000000000000000000000010000
_EM_DENORMAL   = 00000000000010000000000000000000
_EM_AMBIGUOUS  = 10000000000000000000000000000000

                                      divide-by-zero
                                             |
            ambiguous code?                underflow
                  |                          : |
                  v                          v v
Exception code = 11000000000000000000001010110101
                             ^              ^ ^ ^
                             |              : : |
                     denormal number     inexact number
                                            : |
                                          overflow
                                            |
                                     invalid number
No divide by zero found here!
result = 0

它已经发现了一个问题(很大),但并没有完全正确地诊断出来。

更糟糕的是,当该子句被调用缺少依赖项的dll替换时,我得到:

代码语言:javascript
复制
                       f.p. exceptions
     denormal number         |
            |               _|_
            v              /   \
11000000011011010000000001111110
         ^^  ^ ^         ^^
         ||  | |         ||
         \________________/
           unknown codes

在SIGSEV错误(分段错误)的情况下,返回类似的结果。这意味着我们将其他问题误认为是浮点异常。

所以我的问题是:

  1. 这个一般的方法是正确的,还是我误解了一些基本的东西?
  2. 为什么这不是简单的除以零的例子呢?硬件依赖吗?
  3. 我能否找到GetExceptionCode()中的其他错误位--这将是非常有用的。

PS:请不要评论或回复说我应该检查分母是否是0,我知道,我在我控制的所有代码中都这样做。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-06 13:17:18

你需要一些类似的东西

代码语言:javascript
复制
DWORD exception_filter(DWORD dwExceptionCode)
{
    // use dwExceptionCode to handle only the types of exceptions you want
    // if you want to use it inside your handler, you'll need to save it.
    return EXCEPTION_EXECUTE_HANDLER; // or other value depending on ExceptionCode
}

Your exception handler...

__try
{
    something();
}
__except (exception_filter(GetExceptionCode())
{
    // DO NOT CALL GetExceptionCode() or GetExceptionInfo() here. If you need
    // Exception Info as well, pass it to the filter, and save the values you need.
    switch (dwSavedExceptionCode)
    {
        case EXCEPTION_FLT_OVERFLOW:
              ItWasAFloatingPointOverflow(); 
              break;
        case EXCEPTION_FLT_DIVIDE_BY_ZERO:
              ItWasAFloatingDivideByZero(); 
              break;
        case ***Other Exception Types You Want handled (==the ones you returned execute_handler for in the filter) ***
              break;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2017-01-06 19:02:02

异常代码=1100000000000000000000001010110101

这个值是0xC00002B5,又名STATUS_FLOAT_MULTIPLE_TRAPS

Why after enabling floating point exceptions I got multiple traps error

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41505721

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档