デストラクターからスローされた例外

C++ デストラクターが例外をスローしているか、その可能性があります。

次の 2 つの理由から、C++ デストラクターは例外をスローすべきではありません。1 つ目の理由として、C++ オブジェクトは、例外が許可されていないコンテキストで暗黙的に破棄されます。例えば、例外 E1 をスローするデストラクターを持つオブジェクト X のインスタンスをブロックの中で宣言して、 別の例外 E2 をスローしてそのブロックを終了する場合、 C++ ランタイムは E1 と E2 の両方の例外ハンドラーを実行することはできません。どちらか一方を選択すると、もう片方の例外は失われます。例外を失うことはできないため、C++ ランタイムは、プロセスを直ちに終了する terminate() を呼び出します。

2 つ目の理由として、デストラクターが例外のスローに成功し、例外が正しく処理されたとしても、アプリケーションでメモリーリークが発生します。オブジェクトの削除では、最初にデストラクターが呼び出され、次に delete 演算子が呼び出されます。実際にストレージを解放するのは delete 演算子です。デストラクターが例外をスローして、delete 演算子が呼び出されなかった場合、メモリーリークが発生します。

ID

問題箇所

説明

1

例外のスロー

例外がスローされた場所

2

定義

デストラクターが定義された場所

          
#include <stdio.h>
#include <stdlib.h>

class Bomb { // bad class throws exception from destructor
    int x;
public:
    Bomb() : x(0) {}
    ~Bomb() { throw "boom"; }
    
    void * operator new(size_t n) throw()
    {
        printf("operator new called\n");
        return malloc(n);
    }
    
    void operator delete(void *p) throw()
    {
        printf("operator delete called\n"); // never gets here
        if (p != 0) free(p);
    }
};

void f() {
    Bomb myBomb; // local variable that will blow up when torn down
    
    Bomb *pBomb = new Bomb();
    try {
        delete pBomb;
    } catch (...) {
        // Gets here but leaks storage.  Print output shows that
        // operator new was called but operator delete was not.
        printf("caught exception from destructor\n");
    }
    
    // program dies here: can't throw two exceptions
    // ("boom" and "no boom") at the same time.
    throw "no boom"; // program dies here
}

int main(int argc, char **argv)
{
    try {
        f();
    } catch (char *message) {
        printf("f threw %s\n", message); // never gets here
    }
}
        

© 2010 Intel Corporation. 無断での引用、転載を禁じます。