Ваш код дает сбой, потому что вы освобождаете одну и ту же память дважды, потому что вы не определили четкое владение вашими экземплярами записей.
Ваши списки ListaDePonteiros
и ListaDeObjectos
являются избыточными и могут быть удалены,TTreeView
может быть владельцем записей, и вы можете просто Dispose()
из них в событии TTreeView.OnDeletion
и покончить с этим 1 .
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
и удалите список 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
, чтобы синхронизировать Tree1
и ListaDeObjectos
при удалении отдельных узлов:
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;
1.Всякий раз, когда вы делаете Dispose()
свой экземпляр записи, убедитесь, что вы набрали raw указатели на PMyRec
, иначе компилятор не будет корректно завершать элементы записи, что приведет к утечке памяти.