このコードでメモリ リークが発生しないのはなぜですか?
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
このコードでメモリ リークが発生しないのはなぜですか?
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
あなたは(不)運が悪いからです。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 p
p でデストラクタを呼び出して、メモリを解放するとします。
char
にはデストラクタがないため、p が指すメモリを削除するだけです。上記の私のコードでは、配列内の各要素を破棄するつもりはありません(これは を呼び出していないためdelete[]
です)。
auto_ptr は、ループ反復の間だけ存続し、反復の完了時にそれに接続されているオブジェクトを解放します。
コンパイラは、この場合、new[]がnewと同じ方法でスペースを割り当てることができることを確認できます。単純なデストラクタを呼び出す必要がないため、要素の数をどこにも保存しません。これが、後で代わりに auto_ptr のデストラクタによってdeletechar
が呼び出されたときにその理由です。 delete[]のメモリブロックは実際にはnewの方法で割り当てられており、その割り当てはdeleteと組み合わせることができるため、問題はありません。
これは、やってはいけないことの例です。new[]をnewに置き換えるかどうかを決定するのは、コンパイラ次第です。delete[]の代わりにdeleteを使用すること、およびその逆の使用は未定義の動作です。
なぜこのようなものを書くのでしょうか? を参照してください。(意図的に配列で delete [] を使用しないでください) deleteとdelete[]の議論について。