2009-07-29 8 views
7

なぜこのコードはではないはメモリリークを引き起こしますか?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

+0

ほとんどの場合、新しいものとdelete []とをペアにし、その逆の場合はリークを引き起こしません。代わりに、メモリを解放しようとするとプログラムがクラッシュするだけです。 – sharptooth

+3

std :: auto_ptrの代わりにboost :: scoped_arrayを試すことができます –

答えて

15

あなたは(国連)幸運なので。 auto_ptrdeleteで、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のローカルバー変数は削除されません。

+0

はい、私は不運です。 ありがとうございます。 – Xeningem

+0

私はこれをコンパイルしましたが、 '_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)'エラーメッセージが表示され、プログラムがクラッシュします。これは2回削除されていることを示していますが、それが起こる可能性は分かりません – zar

+0

'Foo'のデストラクタは実際に' iterCount'timesと呼ばれるでしょうが 'iterCount' *' sizeBig'時間に注意してください – zar

3

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

コンパイラは、この場合に新しい[]新しいと同じようにスペースを割り当てることができていることがわかります - 些細なcharデストラクタを呼び出す必要はありませんので、どこかの要素の数を格納することなく - そしてそれはなぜ後でです[]削除の代わりにのauto_ptrはのデストラクタによって呼び出されたときを削除するメモリ・ブロックが実際に新しいの方法で割り当てられているとを削除すると、その割り当てがペアリングさせることができるのでそれは問題ありません。

これは行わないことの例です。 新しい[]をに置き換えるかどうかは、コンパイラによって異なります。 を使用すると、の代わりにが削除されます。削除[]とその逆は、未定義の動作です。

は []削除対を削除の議論のためのWhy would you write something like this? (intentionally not using delete [] on an array)を参照してください。

+0

GManはこう言います:それは幸運です*削除*はここに*削除[] *と同等ですか? – xtofl

+1

これは、コンパイラが賢明で偶然に開発者を救おうとした結果です。 – sharptooth

+3

コンパイラが巧妙であるという結果ではなく、むしろコンパイラが怠惰で最も簡単なことです(この場合、PODが関係している場合、ある要素と配列のメモリ割り当てが正確に同じであることを意味します)。もちろん、これはU.B.です。したがって、それは特定の実装でうまくいく「幸運」です。そしてIIRCでは、実際には動作しない実装がいくつかあります。 –

関連する問題