[Delphi:90209] TListの開放順序?

362 views
Skip to first unread message

T.Sasaki

unread,
Jan 2, 2008, 9:46:02 AM1/2/08
to Delphi MaillingList
とんちぼ@佐渡です。

TListの開放する順序に制限があるのでしょうか。
以下のソースで終了時(OnClose)にエラー
「プロジェクト XXX.exeが EInvalidPointer クラスの例外を発生しました。」
Invalid pointer operation
プロセスは停止しています。再開するには・・・・・・・・」
が出るのですが
「この行」を「変更後行」に移動するとエラーが出ません。
SetLengthの順序とかTListの開放順序に制限があるのでしょうか。
該当する部分を抜き出してコンパイルするとエラーは発生しません。
今までのソースに追加した部分を抜き出してみました。
Delphi6 + Win2Kです。


unit Test;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
    {
幾つかのList有り
}

pStateList = ^StateRecR ;
StateRecR = Record
DevIP : String ;
DevID : Byte ;
DevName : String ;
{
:
:
}
end;

var
Form1: TForm1;

StateRec : array of pStateList ;
StateList : array of TList ;

arrayCnt : Integer ;

implementation

{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
var
i : Integer ;
begin
arrayCnt := 4 ;

    {
幾つかのListのCreate
}

SetLength(StateRec, arrayCnt ) ;  //この行
SetLength(StateList, arrayCnt ) ;
for i := 0 to arrayCnt - 1 do begin
StateList[i] := TList.Create ;
end;
//変更後行
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
i : Integer ;
begin
    {
幾つかのListのFree
}
for i := arrayCnt - 1 downto 0 do begin
while StateList[i].Count > 0 do begin
StateRec[i] := StateList[i].Items[StateList[i].Count - 1] ;
Dispose(StateRec[i]) ;
StateList[i].Delete(StateList[i].Count - 1);
end;
StateList[i].Free ;
end;
end;

end.


khe00221

unread,
Jan 2, 2008, 10:05:03 PM1/2/08
to Del...@ml.users.gr.jp

>該当する部分を抜き出してコンパイルするとエラーは発生しません。

データがないので Dispose(StateRec[i]) ; が実行されない為です

procedure TForm1.Button3Click(Sender: TObject);
var
P : pStateList;
begin
New(P);
StateList[0].Add(P);
Memo1.Lines.Add(IntToStr(Integer(P))); //アドレス表示
New(P);
StateList[0].Add(P);
Memo1.Lines.Add(IntToStr(Integer(P))); //アドレス表示
New(P);
StateList[0].Add(P);
Memo1.Lines.Add(IntToStr(Integer(P))); //アドレス表示
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var

I,J : Integer ;
begin
{
幾つかのListのFree
}
for I := arrayCnt - 1 downto 0 do


begin
while StateList[i].Count > 0 do
begin
StateRec[i] := StateList[i].Items[StateList[i].Count - 1] ;

Memo1.Lines.Add(IntToStr(Integer( StateRec[i]))); //アドレス表示


Dispose(StateRec[i]) ;
StateList[i].Delete(StateList[i].Count - 1);
end;
StateList[i].Free ;
end;

MessageBox(0,'','',0); //止めるため
end;

とデータを追加してCLOSEしたところ正常に終了しましたが?

XP + BDS2006

takefumi-o

unread,
Jan 3, 2008, 12:02:07 AM1/3/08
to Del...@ml.users.gr.jp
あけましておめでとうございます>皆様

レスがつかないようなので若輩ながら私が
お答えさせていただきます。


> procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
> var
> i : Integer ;
> begin
>     {
> 幾つかのListのFree
> }
> for i := arrayCnt - 1 downto 0 do begin
> while StateList[i].Count > 0 do begin
> StateRec[i] := StateList[i].Items[StateList[i].Count - 1] ;
> Dispose(StateRec[i]);

 ここでStateRec[i]に代入するのが問題ではないでしょうか?
 このような場合で開放するときは私でしたら
 var
TempStateRec: pStateList;

 などとし、

 TempStateRec := StateList[i].Items[StateList[i].Count - 1] ;
 Dispose(TempStateRec) ;
 とします。


ちなみに実行部分のコードを見てないのでなんともいえませんが、


>StateList[i].Items[StateList[i].Count - 1]

このItems[StateList[i].Count - 1]はちゃんとNewされているのでしょうか?

TListではなくTList.Itemsの中身に問題があると感じます。


---------------------------------------
mailfrom: Takefumi-o

MailAddress: takef...@gracix.com
HomePageURL: http://www.gracix.com/
---------------------------------------


T.Sasaki

unread,
Jan 3, 2008, 6:56:24 PM1/3/08
to Del...@ml.users.gr.jp
お騒がせしました。

var
StateRec : array of pStateList ;

arrayCnt := 4 ;
SetLength(StateRec, arrayCnt ) ;としたとき
StateRecは[0..3]なのですよね

for i := arrayCnt - 1 downto 0 do begin

従ってi は 3 DownTo 0でOK


while StateList[i].Count > 0 do begin
StateRec[i] := StateList[i].Items[StateList[i].Count - 1] ;
Dispose(StateRec[i]) ;
StateList[i].Delete(StateList[i].Count - 1);
end;
StateList[i].Free ;
end;

しかし実際のソースでは
arrayCnt には 3 が代入され
StateRecは[0..2]の状態になっていて
割り当てられていない領域にアクセスしたためのエラーでした。
検証していただいた方々大変有り難うございました。
初歩的なミスで正月休みをつぶしてしまいました。

T.Sasaki さんは書きました:

Reply all
Reply to author
Forward
0 new messages