7

このコードでメモリ リークが発生しないのはなぜですか?

int iterCount = 1000;
int sizeBig = 100000;
for (int i = 0; i < iterCount; i++)
{
   std::auto_ptr<char> buffer(new char[sizeBig]);
}

WinXP sp2、コンパイラ: BCB.05.03

4

2 に答える 2

15

あなたは(不)運が悪いからです。auto_ptrコールdeleteではありませんdelete []。これは未定義の動作です。

次のようなことを試して、運が良いかどうかを確認してください。

struct Foo
{
    char *bar;
    Foo(void) : bar(new char[100]) { }
    ~Foo(void) { delete [] bar; }
}

int iterCount = 1000;
int sizeBig = 100000;
for (int i = 0; i < iterCount; i++)
{
   std::auto_ptr<Foo> buffer(new Foo[sizeBig]);
}

ここでの考え方は、デストラクタFooが呼び出されないということです。


その理由は次のようなものです:delete[] pの実装はdelete[]、配列内の各要素に移動し、そのデストラクタを呼び出してから、p が指すメモリを解放することを想定しています。同様に、delete pp でデストラクタを呼び出して、メモリを解放するとします。

charにはデストラクタがないため、p が指すメモリを削除するだけです。上記の私のコードでは、配列内の各要素を破棄するつもりはありません(これは を呼び出していないためdelete[]です)。

于 2009-07-29T07:35:16.487 に答える
3

auto_ptr は、ループ反復の間だけ存続し、反復の完了時にそれに接続されているオブジェクトを解放します。

コンパイラは、この場合、new[]がnewと同じ方法でスペースを割り当てることができることを確認できます。単純なデストラクタを呼び出す必要がないため、要素の数をどこにも保存しません。これが、後で代わりに auto_ptr のデストラクタによってdeletecharが呼び出されたときにその理由です。 delete[]のメモリブロックは実際にはnewの方法で割り当てられており、その割り当てはdeleteと組み合わせることができるため、問題はありません。

これは、やってはいけないことの例です。new[]newに置き換えるかどうかを決定するのは、コンパイラ次第です。delete[]の代わりにdeleteを使用すること、およびその逆の使用は未定義の動作です。

なぜこのようなものを書くのでしょうか? を参照してください。(意図的に配列で delete [] を使用しないでください) deletedelete[]の議論について。

于 2009-07-29T07:35:21.773 に答える