我使用Delphi7。我创建了一个存储信息的记录,并使用指针将该记录作为对象存储在包含100多个项目的TreeView中。
我的问题是,如何从内存中释放或消除所有这些对象?
type
PMyRec = ^TMyRec;
TMyRec = record
Tipo: string;
parent: string;
end;
var
MyRecPtr: PMyRec;
for x := 1 to 100 do
begin
New(MyRecPtr);
MyRecPtr^.Tipo := '1';
MyRecPtr^.parent := 'paul';
Tree1.Items.AddChildObject(nil, IntToStr(x) + '-NewItem', MyRecPtr);
ListaDePonteiros.Add( MyRecPtr ); // I use a TList to store pointers
ListaDeObjectos.Add( MyRecPtr ); // I use a TList to store Objects
end;
我如何尝试将其全部删除:
procedure TForm1.Button2Click(Sender: TObject);
procedure EmptyTList(Var AList: TList);
var
intContador: integer;
begin
for intContador := (AList.Count-1) downto 0 do
begin
if Assigned(AList.Items[intContador]) then
begin
Dispose(AList.Items[intContador]);
AList.Items[intContador] := nil;
AList.Delete(intContador);
end;
end;
end;
begin
if Assigned(MyRecPtr) then
begin
EmptyTList(ListaDePonteiros);
end;
end;
当我删除TreeView OnDelete
事件中的所有项目时,我会得到:
if assigned(Node.Data) then
begin
Dispose(Node.Data);
end;
我要做的是从内存中释放所有对象!
如果我使用该列表处理所有对象,那么如果我从TreeView中删除任何项目,则会引发无效的指针错误!
即使配置了所有指针,MyRecPtr
仍指向内存中的某个位置,Node.Data
也指向内存!
答案 0 :(得分:1)
您的代码崩溃是因为您两次释放相同的内存,因为您尚未定义记录实例的任何明确所有权。
您的apitoken
和ListaDePonteiros
列表是多余的,可以删除。 ListaDeObjectos
可以是记录的所有者,您可以在TTreeView
事件中简单地Dispose()
对其进行记录,并对其进行处理 1 。
TTreeView.OnDeletion
否则,如果您选择保留单独的列表,请保留var
MyRecPtr: PMyRec;
for x := 1 to 100 do
begin
New(MyRecPtr);
try
MyRecPtr^.Tipo := '1';
MyRecPtr^.parent := 'paul';
Tree1.Items.AddChildObject(nil, IntToStr(x) + '-NewItem', MyRecPtr);
except
Dispose(MyRecPtr);
raise;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Tree1.Items.Clear;
end;
procedure TForm1.Tree1Deletion(Sender: TObject; Node: TTreeNode);
begin
if Assigned(Node.Data) then
Dispose(PMyRec(Node.Data));
end;
列表并删除ListaDeObjectos
列表(因为没有理由维持2个列表跟踪完全相同的值)。您只需要决定是要ListaDePonteiros
还是ListaDeObjectos
来拥有分配的记录:
如果Tree1
是所有者,请不要在ListaDeObjectos
事件中调用Dispose(Node.Data)
。
TTreeView.OnDeletion
如果要成为var
MyRecPtr: PMyRec;
Idx: Integer;
for x := 1 to 100 do
begin
New(MyRecPtr);
try
MyRecPtr^.Tipo := '1';
MyRecPtr^.parent := 'paul';
Idx := ListaDeObjectos.Add(MyRecPtr);
try
Tree1.Items.AddChildObject(nil, IntToStr(x) + '-NewItem', MyRecPtr);
except
ListaDeObjectos.Delete(Idx);
raise;
end;
except
Dispose(MyRecPtr);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
procedure EmptyTList(AList: TList);
var
intContador: integer;
begin
for intContador := 0 to (AList.Count-1) do
Dispose(PMyRec(AList[intContador]));
AList.Clear;
end;
begin
Tree1.Items.Clear;
EmptyTList(ListaDePonteiros);
end;
的所有者,请不要在Tree1
中调用Dispose(AList.Items[intContador])
(实际上,您可以完全摆脱EmptyTList()
,而只是打电话EmptyTList()
(如果需要)。
ListaDeObjectos.Clear()
无论哪种方式,当一口气都无法大规模清除var
MyRecPtr: PMyRec;
Node: TNode;
for x := 1 to 100 do
begin
New(MyRecPtr);
try
MyRecPtr^.Tipo := '1';
MyRecPtr^.parent := 'paul';
Node := Tree1.Items.AddChildObject(nil, IntToStr(x) + '-NewItem', MyRecPtr);
except
Dispose(MyRecPtr);
raise;
end;
try
ListaDePonteiros.Add(MyRecPtr);
except
Node.Free;
raise;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ListaDePonteiros.Clear;
Tree1.Items.Clear;
end;
procedure TForm1.Tree1Deletion(Sender: TObject; Node: TNode);
begin
if Assigned(Node.Data) then
Dispose(PMyRec(Node.Data));
end;
和Tree1
时,请考虑在ListaDeObjectos
事件中调用ListaDeObjectos.Remove()
来保持TTreeView.OnDeletion
和{删除单个节点时,{1}}已同步:
Tree1
1。每当您ListaDeObjectos
执行记录实例时,请确保将 raw 指针类型转换为procedure TForm1.Tree1Deletion(Sender: TObject; Node: TNode);
begin
if Assigned(Node.Data) then
begin
// only if the TreeView is the owner...
Dispose(PMyRec(Node.Data));
ListaDeObjectos.Remove(Node.Data);
end;
end;
,否则编译器将无法正确确定记录的成员,从而泄漏内存。