7

動的に割り当てられたクラスで例外をスローするとどうなるかについて、何人かの同僚と議論していました。mallocそれが呼び出され、次にクラスのコンストラクターが呼び出されることを知っています。コンストラクターは決して返らないので、 ? はどうなりmallocますか?

次の例を検討してください。

class B
{
public:
    B()
    {
        cout << "B::B()" << endl;
        throw "B::exception";
    }

    ~B()
    {
        cout << "B::~B()" << endl;          
    }
};

void main()
{
    B *o = 0;
    try
    {
        o = new B;
    }
    catch(const char *)
    {
        cout << "ouch!" << endl;
    }
}

malloced memoryoはどうなりますか? リークしますか? CRT はコンストラクターの例外をキャッチし、メモリの割り当てを解除しますか?

乾杯!
リッチ

4

4 に答える 4

10

への呼び出し

new B();

次の 2 つの点で解決します。

  • 演算子 new() による割り当て (グローバルなものまたはクラス固有のもの、潜在的に構文を持つ配置のものnew (xxx) B())
  • コンストラクターの呼び出し。

コンストラクターがスローした場合、対応する演算子 delete が呼び出されます。対応する削除が配置 1 の場合は、構文 ::operator delete() なしで配置削除演算子が呼び出される唯一のケースです。 delete x;またはdelete[] x;、placement delete 演算子を呼び出さないでください。placement new と同様の構文でそれらを呼び出すことはできません。

B のデストラクタは呼び出されませんが、すでに構築されたサブオブジェクト (メンバーまたは B と B の基本クラス) は、演算子 delete の呼び出しの前に破棄されることに注意してください。呼び出されないコンストラクタは B 用のものです。

于 2009-08-20T13:17:57.330 に答える
1

C++ 2003 標準 5.3.4/17 から - 新規:

上記のオブジェクト初期化のいずれかの部分が例外をスローして終了し、適切な割り当て解除関数が見つかると、割り当て解除関数が呼び出されて、オブジェクトが構築されていたメモリが解放されます。その後、例外はコンテキスト内で伝播し続けます。 new-expression の。明確に一致する割り当て解除関数が見つからない場合、例外を伝播してもオブジェクトのメモリは解放されません。[注: これは、呼び出された割り当て関数がメモリを割り当てない場合に適しています。そうしないと、メモリ リークが発生する可能性があります。]

したがって、リークがある場合とない場合があります - 適切なデアロケータが見つかるかどうかに依存します (演算子 new/delete がオーバーライドされていない限り、通常はそうです)。適切なデアロケータがある場合、コンパイラが責任を負います。コンストラクターがスローした場合に呼び出しで配線するため。

これは、コンストラクターで取得したリソースに何が起こるかとは多かれ少なかれ無関係であることに注意してください。これは、私の最初の回答の試みで説明したものであり、多くの FAQ、記事、および投稿で説明されている質問です。

于 2009-11-04T17:13:43.037 に答える