为什么抛出"无"会导致程序终止?

aJ.*_*aJ. 14 c++ exception-handling

const int MIN_NUMBER = 4;
class Temp
{
public:

    Temp(int x) : X(x)
    {
    }

    bool getX() const
    {
        try
        {
            if( X < MIN_NUMBER)
            {
                //By mistake throwing any specific exception was missed out
                //Program terminated here
                throw ;
            }
        }
        catch (bool bTemp)
        {
            cout<<"catch(bool) exception";

        }
        catch(...)
        {
            cout<<"catch... exception";
        }
        return X;
    }

private:
    int X;
};



int main(int argc, char* argv[])
{
    Temp *pTemp = NULL;
    try
    {
        pTemp = new Temp(3);
        int nX = pTemp->getX();
        delete pTemp;
    }
    catch(...)
    {
        cout<<"cought exception";
    }

    cout<<"success";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,throw false意在getX()方法中,但是由于人为错误(!)错过了错误.看起来无辜的代码使应用程序崩溃了.

我的问题是为什么当我们抛出"没有"时程序会被终止?

我几乎没有理解throw;基本上是"重新抛出",必须在异常处理程序(catch)中使用.在任何其他地方使用这个概念会导致程序终止,那么为什么编译器在编译期间不会引发标志?

小智 28

这是预期的行为.从C++标准:

如果当前没有处理异常,则执行不带操作数的throw-expression调用terminate()(15.5.1).

至于为什么编译器无法诊断这一点,需要进行一些相当复杂的流程分析,我想编译器编写者不会认为它具有成本效益.C++(和其他语言)充满了可能的错误,理论上这些错误可能被编译器捕获但实际上并非如此.

  • aJ,没关系.人们可以从catch块中调用该函数然后抛出; 已验证. (2认同)

Aar*_*ron 12

详细说明尼尔的答案:

throw;本身将尝试重新提升当前正在解除的异常 - 如果多个被解开,它会尝试重新抛出最近的异常.如果没有被解开,则调用terminate()来表示你的程序做了一些虚假的事情.

至于你的下一个问题,为什么编译器不会throw;在catch块之外发出警告,编译器无法在编译时告诉该throw;行是否在catch块的上下文中执行.考虑:

// you can try executing this code on [http://codepad.org/pZv9VgiX][1]
#include <iostream>
using namespace std;

void f() {
    throw 1;
}
void g() {
    // will look at int and char exceptions
    try { 
        throw;
    } catch (int xyz){
        cout << "caught int " << xyz << "\n";
    } catch (char xyz){
        cout << "caught char " << xyz << "\n";
    }
}
void h() {
    try {
        f();
    } catch (...) {
        // use g as a common exception filter
        g();
    }
}
int main(){
    try {
        h();
    } catch (...) {
        cout << "some other exception.\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

在此程序中,g()作为异常过滤器运行,可以从h()可以使用此异常处理行为的任何其他函数中使用.您甚至可以想象更复杂的情况:

void attempt_recovery() {
    try{
        // do stuff
        return;

    } catch (...) {}

    // throw original exception cause
    throw;
}
void do_something() {
    for(;;) {
        try {
            // do stuff
        } catch (...) {
            attempt_recovery();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这里,如果在do_something中发生异常,则将调用恢复代码.如果该恢复代码成功,则会忘记原始异常并重新尝试该任务.如果恢复代码失败,则忽略该故障并重新抛出先前的故障.这是有效的,因为throw;在catch块attempt_recovery的上下文中调用了in do_something.


Mic*_*urr 10

从C++标准:

15.1抛出异常

...

如果当前没有处理异常,则执行不带操作数调用的throw-exception terminate()

编译器无法可靠地捕获此类错误的原因是异常处理程序可以调用函数/方法,因此编译器无法知道是否throw在a中发生catch.这基本上是一个运行时的东西.