例外をスローするとメモリは解放されますか?
-
19-09-2019 - |
質問
私は動的に割り当てられたクラスで例外をスローした場合に何が起こるかについて何人かの同僚と議論していました。私はそれを知っています 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;
}
}
再配置されたメモリはどうなるか o
, 、漏れますか?CRT はコンストラクターの例外をキャッチし、メモリの割り当てを解除しますか?
乾杯!
リッチ
解決
への電話
new B();
次の 2 つの点で解決されます。
- 演算子 new() を使用して割り当てます (グローバルな演算子またはクラス固有の演算子、場合によっては構文を使用した配置演算子)
new (xxx) B()
) - コンストラクターを呼び出します。
コンストラクターがスローすると、対応する演算子 delete が呼び出されます。対応する削除が配置削除である場合は、配置削除演算子が構文 ::operator delete() なしで呼び出される唯一のケースです。 delete x;
または delete[] x;
配置削除演算子を呼び出さないでください。また、それらを呼び出すための配置新規と同様の構文はありません。
B のデストラクタは ない が呼び出されると、既に構築されたサブオブジェクト (メンバーまたは B および B の基本クラス) は、オペレーター delete の呼び出し前に破棄されます。呼び出されないコンストラクターは B のコンストラクターです。
他のヒント
例外はコンストラクタからスローされた場合、新しいによって割り当てられたメモリが解放されますが、クラスBのデストラクタが呼び出されません。
この場合、あなたのオブジェクトは、O、実際に構築されていませんし、新しいによって割り当てられたメモリが解放されます。そのため、デストラクタが呼び出されません。だから、呼び出す必要はありません。
delete o;
興味深いデザインパターンはRAIIです - リソースの取得は初期化されています。このパターンでは、リソースの獲得をカプセル化し、デストラクタでリソースを解放するために、コンストラクタを使用しています。リソースが取得できない場合は、コンストラクタでスロー - ずっとあなたの例のように。あなたが有効なオブジェクトを持っている場合はこのように、あなたはリソースを持っています。
オブジェクトが構築されている場合は、、あなたは成功したリソースを取得しています。これは、オブジェクトの人生のために、あなたがリソースを所有していることを意味します。オブジェクトが削除されると、リソースが解放されます。オブジェクトが構築されることはありません場合は、リソースを取得することはありません。ウィキペディアを参照してください。
http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initializationする
C ++ 2003の標準5.3.4 / 17から - 新しいます:
見つけることができ、上述のオブジェクトの初期化のいずれかの部分が例外と適切な解放機能を投げることによって終了した場合、、解放機能は、例外が伝播し続けた後、オブジェクトが構築されたメモリを解放するために呼び出されますnew式のコンテキストインチ何の明確な一致解放関数が見つからない場合は、例外を伝播すると、オブジェクトのメモリが解放されることはありません。 [注:呼び出さ割り当て機能は、メモリを割り当てられない場合に適切です。それ以外の場合は、メモリリークが発生する可能性があります。
だから又は漏れがあってもなくてもよい - それは(オペレータ新しい/削除がオーバーライドされていない限り、通常の場合である)適切なデアロケータを見つけることができるかどうかに依存して適切なデアロケータがあります場合.IN、コンストラクタがスローした場合、コンパイラは、それへの呼び出しで配線する責任があります。
これは、多かれ少なかれ答えで私の最初の試みが議論するもので、コンストラクタ、で取得したリソースに何が起こるかには無関係であることに注意してください - 。そして多くのFAQ、記事、および投稿で説明して質問です。