4

誰かが次の状況を処理する正しい方法を説明してください:

wchar_t* buffer = new wchar_t[...];

if (!something)
{
    throw std::runtime_error("Whatever");
    // Now, at this point I'm leaking memory allocated for the 'buffer'.
}

// Perform actions.
delete[] buffer;

それを解決する明白な方法は、次のようなことを意味します。

if (!something)
{
    delete[] buffer;
    throw std::runtime_error("Whatever");
}

さて~いいですか?(私はそう思うが、誰が知っているか:)


PS私はそれを行うためのはるかに良い方法があることを認識しています - を使用するboost::scoped_arrayか、単純std::wstringに、呼び出されたデストラクタが割り当てられたメモリを解放できるようにします

4

5 に答える 5

8

あなたの洞察は正しいです。パターン

Acquire some resource
Do something
Release resource

Do something例外をスローしてリソースをリークする可能性があるため、根本的に間違っています。さらに、エラーの発生源であるリソースを解放することを忘れないでください。

ご指摘のとおり、正しい方法は、デストラクタがリソースを解放するオブジェクトを常に使用することです。これは、C++ではRAIIという名前で呼ばれます。

これは、例えばを意味します。外部デストラクタを使用しdeleteたり、ファイルハンドルを手動で閉じることに依存したり、ミューテックスのロックを手動で解除したりしないでください。スマートポインタについて学び、可能な限りそれらを使用してください。

一部の言語(C ++ではない)にはfinallyキーワードが用意されており、例外がスローされたかどうかに関係なく、命令のブロックを実行できます。C ++はRAIIを使用するため、適切なデストラクタを作成する場合は、リソースの解放について心配する必要はありません。

C ++ 0xには、ブロックの終了時に任意のコードを実行できるユーティリティが少しあります。これは、記述が不十分な(またはC)ライブラリと1回または2回インターフェイスする場合に使用します。

于 2011-07-28T08:56:35.623 に答える
0

どこにありcatchますか?同じスコープ内にあるdelete場合は、そこで処理できます。それ以外の場合は、#2が適切なオプションです。もちろん、PSであなた自身が述べたようにあなたがそれを正しい方法でやりたくないと仮定すると...

于 2011-07-28T08:56:05.953 に答える
0

それは何かに依存します。コンピューティングsomethingが例外をスローする可能性がある場合、いいえ、それは問題ありません。スタックに割り当てられた変数(スコープの最後で破棄される)を使用するか、さまざまな種類のスマートポインター(stdライブラリ、ブースト、選択)を使用して、取得するすべてのリソースを処理する必要があります。

于 2011-07-28T08:56:43.360 に答える
0

正しい方法は、RAIIパターンを使用することです。生のポインタを使用するのではなく、デストラクタのメモリの解放を処理するオブジェクト(astd::wstringや。など)でラップする必要がありますstd::unique_ptr

于 2011-07-28T08:57:48.860 に答える
0

ラップされていないnewを明示的に使用する場合は、deleteを明示的に使用する必要があります。したがって、この場合、例外をキャッチしてからdeleteを呼び出す必要があります。

あなたが言うように、正しい方法は、デストラクタが呼び出されるC++クラスでバッファをラップすることです。単純なバッファーの場合、オーバーヘッドが最小のクラスはおそらくstd :: vectorですが、boost::scoped_ptrなどのスマートポインターも同様に機能します。

于 2011-07-28T08:58:13.913 に答える