deleteの成功条件について教えてください

解決


dudley3rd  2009-11-15 17:32:13  No: 71102  IP: [192.*.*.*]

DirectXの参考書のサンプルコードで以下のような事と同じ事をしている部分があったのですが 
よろしければ、この場合にはnewで確保したメモリはきちんと解放されるのかを教えてください。 
また、今後のために以下の事を教えてくだされば幸いです。
1.確保したメモリが解放されていることの確認方法
2.deleteの成功する条件

#include<stdio.h>

int main(void)
{
    if(1)
    {
        int* p2;
        if(1)
        {
            int* p;
            p = new int[3];

            p[0]=10;
            p[1]=20;
            p[2]=30;
            p2=p;

            p=NULL;
            delete [] p;
        }
    }
    return 0;
}

私の浅い言語経験で考えた状況としては下の2つくらいです。 
1.newで確保した部分と全く違う部分を解放しようとしているので 
  当然メモリは確保され続ける
2.deleteは成功しているので後はp2がスコープから外れればメモリは解放される

編集 削除
fuku  2009-11-15 19:45:43  No: 71103  IP: [192.*.*.*]

このコードではnewされたオブジェクトは解放されません。

delete[]が呼ばれた時点でpはNULLですから、
仕様に従い何も起こりません。(NULLに対してdeleteした場合は無視する)

よってp2に保持されたオブジェクトは引き続き存続していて、
p2が消滅した(スコープから外れた)時点で解放するべきポインタを見失い、メモリリーク(解放ミス)となります。
解放するにはp2が消滅する前にdelete[] p2しなければいけません。


なお、C++言語では
>2.deleteは成功しているので後はp2がスコープから外れればメモリは解放される 
というような状況は存在しません。
deleteが実行された時点からそのオブジェクトへのアクセスは認められず、
deleteされたポインタを保持するポインタ変数の消滅を待つことはありません。

したがって、p=NULLをせずにdelete[] pしたなら、p2も同時にアクセスできなくなります。


>1.確保したメモリが解放されていることの確認方法
deleteは正しく実行されれば必ず成功することになっている(はず)ですので、通常は確認する術はありません。
ただし、デバッグビルドしている場合、解放した領域を特徴的な値で埋め立てる場合があります。
デバッガを使ってそのような埋め立てが行われたかを見るという方法はあるかと思います。

>2.deleteの成功する条件
「対応するnew(deleteはnew、delete[]はnewの配列版)で確保し、newが返したポインタで、まだ解放されていないもの」、
またはNULL(無視されます)を渡した場合。

これを満たさないdeleteの使用は不定の結果となります。

編集 削除
dudley3rd  2009-11-15 20:07:36  No: 71104  IP: [192.*.*.*]

大変分かりやすい説明をありがとうございました。
まだまだC言語を学びたてでこれからもご迷惑をおかけするかもしれませんが、よろしくお願いいたします。

編集 削除