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.
データがないので 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
レスがつかないようなので若輩ながら私が
お答えさせていただきます。
> 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/
---------------------------------------
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 さんは書きました: