New(P)を使ったあとの解放方法は?

解決


  2007-03-15 23:04:59  No: 25337

お世話になります。環境はWindows XP Pro  Delphi 6 Personalです。
質問1:素人が作成したプログラムだからメモリーリークがあるだろ〜な〜とは考えていましたが、ふとしたきっかけでメモリーリークをチェックできるソフトを下記のサイトで見つけました。
そこで実行してみると2700個(TreeViewの要素数と同じ)くらいチェックに引っかかり仰天しました。下記のNew()を外すとほぼ0になります。
コードはお気に入りをテキストファイルに保存していて、それを起動時にTreeViewにロードするとき発生するのが判りました。
ヘルプにNew()を使ったらDispose()で解放することと書いてありましたから、適当と考えられる場所にいれるとリークは0になりますが  TreeViewのNodeのURLが空白で入るようでうまくいきません。
TreeViewに要素名+URLを登録するサイトは散見するのですがDisposeを書いてあるのを見かけません。不要なのでしょうか?
質問2:以前この掲示板には過去ログ検索が合ったような気がするのですが見あたりません。ブラウザがおかしいのかといろいろ試しました。なぜ無くなったのでしょうか?大変お世話になっていたので残念です。
よろしくお願いします。

TOBY SOFT wiki の  Delphi  メモリーリークをチェックするの  HeapChecker
http://tobysoft.net/wiki/index.php?Delphi%2F%A5%E1%A5%E2%A5%EA%A5%EA%A1%BC%A5%AF%A4%F2%A5%C1%A5%A7%A5%C3%A5%AF%A4%B9%A4%EB

type
    PBookMarkItem = ^TBookMarkItem;
    TBookMarkItem = record
    URL:string;
  end;
・・・・
var
   P:PBookMarkItem;
    Node:TTreeNode;
    StringListNode,  strList :TStringList;
begin
・・・・
        //お気に入りテキストファイルをロードする  構造  "level","要素名","http://......URL"
        StringListNode.LoadFromFile(AppPath+'ScrapbookData\_ScrapBookSystem\IEFavorites.txt');
        OldLevel := 0;   //integer
        Node := nil;     //

        for i := 0 to StringListNode.Count -1 do
        begin
            StrList.CommaText := StringListNode.Strings[i];
            NewLevel :=   StrToInt(StrList.Strings[0]) ;        //レベル
            strTitle := StrList.Strings[1];            //項目名
            New(P);
            P^.URL := StrList.Strings[2];            //URL
            Node := formMDI.TreeView1.Items.AddObject(Node,strTitle,P)
            if OldLevel > NewLevel then
            begin
                OldLevel := NewLevel;
                while Node.Level > NewLevel do
                begin
                    Node.MoveTo(Node.Parent,naAdd);
                end;
            end
            else
            begin
                if OldLevel < NewLevel then //子にする
                begin
                    Node.MoveTo(Node.GetPrev,naAddChild);
                    OldLevel := NewLevel;
                end;
            end;
      Dispose(P);//・・・・・・・・・此処に入れてみましたがURLがクリアーされるみたい
        end;


HOta  2007-03-16 02:57:37  No: 25338

TStringListには、Pのアドレスが入りますので、すぐに
Disposeすると、TStringListの中身がなくなります。TStringListを開放するときにDisposeしましょう。


  2007-03-16 21:24:54  No: 25339

HOtaさん、さっそく教えて頂きありがとうございました。
これで悩みが一つ消えます。
さっそく実行させてもらいます。
では。


  2007-03-16 23:28:10  No: 25340

このコードの終了時、StringListNode.FreeのあとにDispose(P);を実行したのですが効果はありませんでした。
引き続き勉強してみます。
では。


HOta  2007-03-17 00:21:17  No: 25341

Freeしてしまうと、DisposeするPのアドレスもなくなります。
Freeの前ですよ。


Basser  2007-03-17 00:23:25  No: 25342

Disposeの前に

  P^.URL:= '';

も必要だと思います。

後、解放のタイミングはTTreeViewの各NodeのDataプロパティが必要で無くなった時です。


  2007-03-17 23:17:55  No: 25343

HOtaさん、Basser さん、ありがとうございます。
ずっとトライしているのですが、起動時にTreeViewにここでお気に入りを登録して、先のコードのあとは
・・・ 
   finally
        P^.URL:= '';
        Dispose(P);
        StringListNode.Free;
        strList.Free;
    end;
end;
で終わるだけですが、起動中はお気に入りをずっと使います。
前記のように記述してプログラムを終了すると「約2700個のヒープ領域が未解放です」と出るのですがこれは異常では無いのでしょうか?
記述場所が悪いのでしょうか?
ちなみに、繰り返しルーチンの中に入れるとURLは空になる代わりにヒープ領域の未解放は0になります。
できればよろしくお願いいたします。


春場所  2007-03-18 00:47:49  No: 25344

>前記のように記述してプログラムを終了すると「約2700個のヒープ領域が未解放です」と出るのですがこれは異常では無いのでしょうか?
それは以上、...でなくて、異常。

>記述場所が悪いのでしょうか?
記述場所は OnDeletionハンドラ。


HOta  2007-03-18 05:55:27  No: 25345

使っている間は、開放すると無くなりますから、しません。
この場合なら、プログラムの終了時に開放します。


  2007-03-18 21:37:16  No: 25346

春場所さん、HOtaさんありがとうございます。
やっとわかりました。
プログラムの後始末についていままで真剣に考慮していませんでした。
いい勉強になりました。ありがとうございました。
では。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加