なぜこのコードはではないはメモリリークを引き起こしますか?std :: auto_ptr、delete [] and leaks
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
なぜこのコードはではないはメモリリークを引き起こしますか?std :: auto_ptr、delete [] and leaks
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[]
を呼び出さないので)配列内の各要素を破棄しないため、Fooのローカルバー変数は削除されません。
auto_ptrはループ反復の間のみ有効で、反復完了時にauto_ptrに接続されているオブジェクトを解放します。
コンパイラは、この場合に新しい[]が新しいと同じようにスペースを割り当てることができていることがわかります - 些細なchar
デストラクタを呼び出す必要はありませんので、どこかの要素の数を格納することなく - そしてそれはなぜ後でです[]削除の代わりにのauto_ptrはのデストラクタによって呼び出されたときがを削除するメモリ・ブロックが実際に新しいの方法で割り当てられているとはを削除すると、その割り当てがペアリングさせることができるのでそれは問題ありません。
これは行わないことの例です。 新しい[]をに置き換えるかどうかは、コンパイラによって異なります。 を使用すると、の代わりにが削除されます。削除[]とその逆は、未定義の動作です。
は []削除対を削除の議論のためのWhy would you write something like this? (intentionally not using delete [] on an array)を参照してください。
GManはこう言います:それは幸運です*削除*はここに*削除[] *と同等ですか? – xtofl
これは、コンパイラが賢明で偶然に開発者を救おうとした結果です。 – sharptooth
コンパイラが巧妙であるという結果ではなく、むしろコンパイラが怠惰で最も簡単なことです(この場合、PODが関係している場合、ある要素と配列のメモリ割り当てが正確に同じであることを意味します)。もちろん、これはU.B.です。したがって、それは特定の実装でうまくいく「幸運」です。そしてIIRCでは、実際には動作しない実装がいくつかあります。 –
ほとんどの場合、新しいものとdelete []とをペアにし、その逆の場合はリークを引き起こしません。代わりに、メモリを解放しようとするとプログラムがクラッシュするだけです。 – sharptooth
std :: auto_ptrの代わりにboost :: scoped_arrayを試すことができます –