C++異常之棧自旋

    在C++的異常處理中,當異常被throw後,從進入try塊起,到異常被catch前,在這期間棧上構造的所有對象都會被自動析構,這一過程稱之爲棧自旋。

 一、對於棧上的對象

#include <iostream>
using namespace std;

class A
{
public:
    A()
    {
        cout<<"A()"<<endl;
    }
    ~A()
    {
        cout<<"~A()"<<endl;
    }
};

int InternalFunc(void)
{
    A a;

    throw(static_cast<int>(0));

    cout<<"InternalFunc normal"<<endl;
}

int ExternalFunc(void)
{
    A b;

    InternalFunc();

    cout<<"ExternalFunc normal"<<endl;
}


int main(void)
{
    try {
        ExternalFunc();
    }catch(int x){
        cout<<x<<endl;
    }catch(...){
        cout<<"exception error"<<endl;
    }

    return 0;
}

    最後的輸出結果爲:

    A()
    A()
    ~A()
    ~A()
    0

    我們可以看到,在異常被throw後,程序一層一層地向上,像乘坐直通車一樣找到對應的catch,這之間棧上的對象會被自動地析構,於是發生了兩次構造兩次析構。

二、對於堆上的空間(特別注意)

   如果我們在try塊中申請了堆上的空間,當異常被throw後,catch之前,程序並不會隱式地釋放堆上所申請的空間,這樣就會造成內存泄漏。

#include <iostream>
using namespace std;

class A
{
public:
    A()
    {
        cout<<"A()"<<endl;
    }
    ~A()
    {
        cout<<"~A()"<<endl;
    }
};

int InternalFunc(void)
{
    A *p = new A;

    throw(static_cast<int>(0));

    cout<<"InternalFunc normal"<<endl;
}

int ExternalFunc(void)
{
    A *p = new A;

    InternalFunc();

    cout<<"ExternalFunc normal"<<endl;
}


int main(void)
{
    try {
        ExternalFunc();
    }catch(int x){
        cout<<x<<endl;
    }catch(...){
        cout<<"exception error"<<endl;
    }

    return 0;
}

    最後輸出的結果是:

    A()
    A()
    0

    可以看到,只發生了兩次構造,並未析構。因爲棧自旋時將那兩個指針看作要銷燬的對象,自然只移動了棧頂指針,並未free掉所指向的堆內存,自然堆上的對象就不會被析構了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章