空ではない例外宣言を含むデストラクター

空ではない例外宣言を含む C++ デストラクターが宣言されています。

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

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

ID

問題箇所

説明

1

定義

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

          
#include <stdio.h>
#include <string.h>

class e1 {
private:
   char msg[100];
public:
   e1(char *p) {
      strncpy(msg, p, sizeof(msg));
   }
   char *tostring() { return msg; }
};

class e2 {
private:
   char msg[100];
public:
   e2(char *p) {
      strncpy(msg, p, sizeof(msg));
   }
   char *tostring() { return msg; }
};

class m {
private:
   char msg[100];
public:
   m(char *p) {
      strncpy(msg, p, sizeof(msg));
   }
   char *tostring() { return msg; }
   ~m() throw(e1)
   {
      if (msg[0] == 'h') throw e1(msg); // bad idea
   }
};

void f() {
    m myVar("help");
    throw new e2("me"); // program fails here: can't throw both e1 and e2
}

int main(int argc, char **argv)
{
    try {
        f();
    } catch (e1 e) {
        printf("caught e1; msg=%s\n", e.tostring());
    } catch (e2 e) {
        printf("caught e2; msg=%s\n", e.tostring());
    }
}
        

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