c++ - 在不同的 C++ 编译器中有通用的解决方案来捕获异常类型被零除,段错误?

标签 c++ visual-c++ gcc clang

在编译器 MSVC、GCC、Clang 或它们的通用包装器中是否有捕获异常的通用解决方案,例如被零除、段错误等,可能在“boost”库中?

当然必须是基于每个编译器的细微差别的通用解决方案。 即使我确实在每个编译器下编写了类似的解决方案,我仍然可以离开并忘记任何细微差别。 例如,我可以使用 SEH 异常在 MSVC 中编写并使用 key 编译它:/ZHa

#include<iostream>
#include<string>

#ifdef _MSC_VER
#include <windows.h>
#include <eh.h>


class SE_Exception
{
private:
    EXCEPTION_RECORD m_er; 
    CONTEXT m_context; 
    unsigned int m_error_code;
public:
    SE_Exception(unsigned int u, PEXCEPTION_POINTERS pep) 
    {
        m_error_code = u;
        m_er = *pep->ExceptionRecord; 
        m_context = *pep->ContextRecord;
    }
    ~SE_Exception() {}
    unsigned int get_error_code() const { return m_error_code; }
    std::string get_error_str() const {
        switch(m_error_code) {
        case EXCEPTION_INT_DIVIDE_BY_ZERO: return std::string("INT DIVIDE BY ZERO");
        case EXCEPTION_INT_OVERFLOW:    return std::string("INT OVERFLOW");
        // And other 20 cases!!!

        }
        return std::string("UNKNOWN");
    }
};

void trans_func(unsigned int u, EXCEPTION_POINTERS* pExp)
{
    throw SE_Exception(u, pExp);
}

#else

struct SE_Exception
{
    unsigned int get_error_code() const { return 0; }
    std::string get_error_str() const { return std::string("Not MSVC compiler"); }
};
#endif

int main() {
#ifdef _MSC_VER
    _set_se_translator( trans_func );
#endif

    try {
        int a = 0;
        int b = 1 / a;
        std::cout << "b: " << b << std::endl;
    } catch(SE_Exception &e) {
        std::cout << "SEH exception: (" << e.get_error_code() << ") " << e.get_error_str() << std::endl;        
    } catch(...) {
        std::cout << "Unknown exception." << std::endl;        
    }

    int b;
    std::cin >> b;
    return 0;
}

最佳答案

除以零和许多其他特定的、与硬件相关的运行时错误(例如无效指针取消引用)是未定义的行为,这意味着实现可以自由地以任何它想要的方式处理它。

专门针对被零除、溢出和其他数学错误,请参阅(强调我的):

5/4 [expr]

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. [ Note: most existing implementations of C ++ ignore integer overflows. Treatment of division by zero, forming a remainder using a zero divisor, and all floating point exceptions vary among machines, and is usually adjustable by a library function. — end note ]

5.6/4 [expr.mul]

The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined.

关于空指针解引用,参见:

8.3.2/5 [dcl.ref]

in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior.

其他具体错误散布在整个标准中,我不会全部引用它们,但你明白了。


既然是UB,没有通用的解决方案来处理。通常,MS Windows 会通过 SEH 传播错误,类 Unix 平台会使用信号,而其他操作系统甚至可能会做其他事情。正如上面引述的那样,甚至可以通过依赖于实现的库调用来调整行为。

唯一真正的解决方案是首先通过在代码中插入相关检查来防止这些错误的发生。

关于c++ - 在不同的 C++ 编译器中有通用的解决方案来捕获异常类型被零除,段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17106448/

相关文章:

c++ - 如何修复损坏的 OpenCL header

.net - Visual C++ 秒表

c++ - 我怎样才能避免编译器错误:std::transform?

在 32 位 CentOS (RHEL) 6 上交叉构建 64 位用户空间程序

c - 如何链接 gcc 和 SDL_image 库?

c++ - ofstream-保存一个函数返回一个txt

c++ - 在 C++ Win32 中获取计算机上的用户配置文件列表

c++ - 如何使用c++生成不相关的随机序列

c++ - 使用 C++ 读取文件的最快方法是什么

gcc - 为什么链接库的顺序有时会导致 GCC 出错?