2011-10-10 17 views
5

次の例では、コンストラクタの実行中に例外が処理されるオブジェクトに対してデストラクタが実行されないため、メモリリークが発生する可能性があります。このメモリリークはどこで処理できますか?コンストラクタ内の例外のキャッチ

#include <exception> 

class MyClass { 

public: 
     MyClass() 
     { 
      c = new char[5]; 
      throw std::runtime_error("test"); 
     } 

     ~MyClass() 
     { 
      delete[] c; 
     } 

private: 
    char *c; 
}; 

int main() 
{ 
    try 
    { 
     MyClass Obj; 

    } 
    catch (std::runtime_error) 
    { 

    } 
} 

答えて

5

あなたは具体的にはRAII、この場合、スマートポインタを使用したほうが良いです。

また、Two Phased Construction戦略を使用することもできます。あなたは常に、コンストラクタ本体の内部try-catchブロックを囲む使用して明示的に動的に割り当てられたすべてのそれらのリソースのために削除していますが、動的に割り当てられているリソースのn数を持っているシナリオを考える呼び出すことができます

、それが明示的に追跡するために本当に厄介になりこのようなシナリオでは、RAIIは、それぞれのリソースが暗黙的に独自の割り当て解除を処理し、各リソースを追跡するオーバーヘッドを持つ必要がないため、最良のソリューションを提供します(catchで割り当てを解除する必要があるリソース)。

boost::scoped_ptrまたはstd::tr1::scoped_ptrは、生のポインタではなくこのシナリオに適しています。

+2

このダウンボートは何が必要ですか? RAIIは、これについて行くための最善の方法であり、そうでなければ誰かが間違って言うならば。あなたがDownvoteに責任があると感じたら、なぜ私たちに説明するのに十分な責任感を感じますか?そして、もしこれが間違っていると感じることができないのであれば、あなたはdownvotingのために十分な資格がありません。 –

+0

は、C++ 11関連のものに基づいたこのソリューションですか? – user103214

+0

これはC++ 03です。 –

6

コンストラクタで例外をキャッチし、整理して(メモリを解放する)、メモリリークなしで例外をスローします。

+0

デストラクタは、コンストラクタ内でメモリリークを起こさずに例外を再現するときには呼び出されませんでした。これには何らかの理由がありますか? – user103214

+1

@ user974191:オブジェクト構築は、コンストラクタの末尾の中括弧までは完了しません。 Destructorは、完了したObjectに対してのみ呼び出されます。コンストラクタが完全に実行されなかった場合、オブジェクトは存在しないため、デストラクタは呼び出されません。 –

1

あなたは例外とメモリの手動処理が一緒にうまく行っていない、と述べたthrow;

と再スロー例外その後、何が必要なクリーンアップを行う、コンストラクタ本体で例外をキャッチすることができます。 cメンバーのメモリを自動的に管理するオブジェクト(例:std::stringstd::vector<char>std::unique_ptr<char[]>など)を使用する方がずっと良いでしょう。上記のようなクラスを作成している場合は、メモリを明示的に管理する必要があります。

4

一方向は、コンストラクタの先頭で条件付き例外を指定してから、メモリを割り当てます。

MyClass() 
    try { 
    c = new char[5]; 
    throw std::runtime_error("test");; 
    } 
    catch(std::runtime_error e) { 
    delete[] c; 
    } 

Demo

MyClass() 
    { 
    if(<condition>) 
     throw std::runtime_error("test"); 
    c = new char[<SIZE>]; 
    } 

他の方法は、コンストラクタを囲む特別try-catch()構文を使用することです。

関連する問題