1

我一直在阅读Jesse Liberty 撰写的《在 21 天内自学 C++ 》一书,并遇到了异常和错误一章。作者使用了这个例子:

int top = 10;
int bottom = 0;
try
{
    cout << "top divided by bottom = ";
    cout << (top / bottom) << endl;
}
catch(...)
{
    cout << "something has gone wrong!" << endl;
}

对他来说效果很好。异常被捕获,输出为:

top divided by bottom = something has gone wrong!

我自己试了一下,收到以下错误:

Unhandled exception at 0x0124152d in stuff.exe: 0xC0000094: Integer division by zero.

整数除以零

根据这个线程,“整数除以零在标准 C++ 中不是例外。” 但是 Visual Studio 显然在这里抛出了一个异常,虽然没有捕捉到它。

我尝试定义topand bottomas double,我收到以下输出:

top divided by bottom = 1.#INF

那么为什么try catch块没有捕获integer division by zero异常呢?

4

2 回答 2

3

用于/EHa切换异常处理模型,使非C++异常可以被try-捕获catch

请注意,如果这样做,所有异步异常都将转换为同步异常,并且您真的不想捕获大多数异常。
因此,不推荐用于一般代码

顺便说一句,盲目地捕捉所有你能做到的东西是一种已知的反模式,只捕捉你真正期望和能够处理的东西。

请参阅此处的__try- __except,它始终可以捕获异步异常:http: //msdn.microsoft.com/en-us/library/s58ftw19.aspx

于 2014-10-11T13:16:52.610 回答
2

这本书可能忽略了告诉你必须使用 /EHa 进行编译。默认为 /EHsc,它不会导致这些 SEH 异常被 catch (...) 捕获。

有 catch (...) catch一切都不是很漂亮。您不希望这种情况发生:

int* p = 0;
try {
    int result = *p / 0;
    std::cout << result << std::endl;
}
catch (...) {
    std::cout << "Division by zero" << std::endl;
}

实际上不是零故障除法,当然不好。更好的鼠标陷阱是将 SEH 异常转换为 C++ 异常。您可以通过安装在发生 SEH 异常时运行的回调来实现,如下所示:

#include <exception>
#include <eh.h>
#include <iostream>

class divisionbyzero_exception : public std::runtime_error {
public:
    divisionbyzero_exception() : std::runtime_error("Division by zero") {}
};

void translate_seh_exception(unsigned int exceptioncode, struct _EXCEPTION_POINTERS* pExp) {
    if (exceptioncode == 0xc0000094) throw divisionbyzero_exception();
}

int main(int argc, char* argv[])
{
    _set_se_translator(translate_seh_exception);
    try {
        int result = argc / 0;
        std::cout << result << std::endl;
    }
    catch (divisionbyzero_exception& ex) {
        std::cout << ex.what() << std::endl;
    }
    return 0;
}

请记住,这是完全不可移植的。

于 2014-10-11T14:44:52.573 回答