deleteが実行されない

[戻る]
タクヤ 2002/05/03(金) 01:44:08
 はじめましてタクヤと申します。突然ですが質問させてください。
Windows98,VC6.0でAppWizardを使っています。
 newで生成したCLayout(自前のクラス)オブジェクトをdeleteで
開放したいのですが、デバッグしてみるとなぜかdeleteが素通りされて
しまいます。もちろん値はNULLにはなっていないのですが...
 ソースは下のようなかんじで、リスト構造になっていて
preLayoutとlttrLayoutというのは1つ前と次のCLayoutクラスの
ポインタです。
 申し訳ありませんがどなたか教えてください。
CLayout::~CLayout(){
    if( lttrLayout ){
        lttrLayout->preLayout = NULL;
        delete lttrLayout;
    }
    if( preLayout ){
        preLayout->lttrLayout = NULL;
        delete preLayout;
    }
}

駄犬 [E-Mail] 2002/05/03(金) 03:29:48
オブジェクト数3個で試したところ、デストラクタがきちんと3回呼ばれましたよ。

CLayout    *pobj1, *pobj2, *pobj3;
pobj1 = new CLayout;
pobj2 = new CLayout;
pobj3 = new CLayout;
pobj1->preLayout  = pobj2;
pobj1->lttrLayout = pobj3;
delete pobj1;

素通りというのはどのように確認しました?
デストラクタにブレークポイントを設定してますか?

また、直接は関係ないけど、子をdeleteする前に孫のポインタをNULLにしちゃっていいんでし
ょうか。deleteし損ねそうな気がするんですが。
・・・と思ってオブジェクト5個で試験したら4回しかデストラクタ呼ばれませんでした。

# リスト構造なんてもう忘れかけなので断言できないけど。(^^;

タクヤ 2002/05/03(金) 04:08:52
 レスありがとうございます。

>素通りというのはどのように確認しました?
>デストラクタにブレークポイントを設定してますか?
 とりあえずデバッグの「カーソルの位置まで実行」でデストラクタの最初まで実行して
それから1行ずつ見ているのですが、deleteのところで何の関数も呼ばれず
そのまま次の行に行ってしまい、そのポインタもNULLになっていません。

>また、直接は関係ないけど、子をdeleteする前に孫のポインタをNULLにしちゃっていいんでし
>ょうか。deleteし損ねそうな気がするんですが。
 このクラスは双方向リストになっていて、preLayoutのlttrLayoutとlttrLayoutの
preLayoutというのはもとのCLayoutオブジェクトを指しているので、
NULLにしてからdeleteしないとデストラクタの中で再びそのオブジェクトに対して
deleteが行われてしまうのでNULLにした方がいいと思ったのですがこれじゃ
まずいんでしょうか。

駄犬 [E-Mail] 2002/05/03(金) 14:59:47
>これじゃまずいんでしょうか。
いやいや、私が二分木のような使い方を想像しただけなので、双方向となると私の疑問は当て
はまりません。
# コードに問題があるかないかは別問題ですよ。(^^;

テストプログラム組みなおしてみた。
オブジェクト数3個。うーん、期待通り動きます。。。
単にステップ実行ではデストラクタの動きが確認できないだけじゃないのかな。「カーソルの
位置まで実行」ではなくブレークポイントをデストラクタの先頭に設定してみてください。

それでもダメならビルドしなおしてみるとか。。。

今は時間がないのでここまで。
とりあえず私が試したコードを転載します。(デストラクタは省略)
int main()
{
    CLayout *pobj1, *pobj2, *pobj3;
    pobj1 = new CLayout;
    pobj2 = new CLayout;
    pobj3 = new CLayout;
    pobj1->init(pobj2, pobj3);
    delete pobj1;
    return 0;
}

CLayout::CLayout()
{
    preLayout = lttrLayout = NULL;
}

void CLayout::init(CLayout *pre, CLayout *lttr)
{
    if (pre) {
        preLayout  = pre;
        preLayout->lttrLayout = this;
    }
    if (lttr) {
        lttrLayout = lttr;
        lttrLayout->preLayout = this;
    }
}

ワルツ 2002/05/03(金) 15:09:14
deleteしたからといって、NULLにはならないでしょう。

saito( ); 2002/05/03(金) 16:29:44
ど素人の意見として聞いてください。

newで生成したCLayout(自前のクラス)オブジェクトをdelete
したものを
再度、newにてCleateしたらErrorがでますか?

でなかったら、deleteされているし、
でたら、deleteされていないと思いますが、

私の場合では、Debugでの『表面上』の素通は
一杯ありました。
また、ワルツさんのおっしゃるように、
全部が全部 NULL、0X0000000・・・には
なりませんでした。

実行時の状況が判らなかったので、
検討違いの話しかも分かりませんが・・・

タクヤ 2002/05/03(金) 17:41:58
[[解決]]
 みなさんありがとうございます。おかげさまで解決しました。

>単にステップ実行ではデストラクタの動きが確認できないだけじゃないのかな。「カーソルの
>位置まで実行」ではなくブレークポイントをデストラクタの先頭に設定してみてください。
 その通りでした。ブレークポイントを使ったらちゃんとデストラクタが呼ばれていました。

>deleteしたからといって、NULLにはならないでしょう。
 すみません、私の認識不足でした。
てっきりdeleteしたポインタはNULLになるものだと思い込んでいました。

>newで生成したCLayout(自前のクラス)オブジェクトをdelete
>したものを
>再度、newにてCleateしたらErrorがでますか?
 確かに再度newで作ったオブジェクトを割り付けてもエラーは出ないのですが、
deleteされていなくても新しいオブジェクトのアドレスがポインタに代入されるだけなので
メモリリークはあってもエラーは出ないと思うのですが、
また私の勘違いでしたらすみませんが教えてください。

 こんな勘違いだらけの質問に答えてくださってありがとうございました。
また的外れな質問をしに来るかもしれませんが、よろしくお願いします。

古いスレッドには追加発言できません。