How to release Objects stored in a TreeView from memory?
I use Delphi 7. I create a record that stores info, and using pointers I store that record as an object in a TreeView with more than 100 items.
My problem is, how to release or eliminate all these objects from memory?
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;
How I try to delete them all:
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;
When I delete all items in the TreeView OnDelete
event, I have this:
if assigned(Node.Data) then
begin
Dispose(Node.Data);
end;
What I want to do is release all objects from memory!
If I dispose all objects using that list then if I delete any item from the TreeView an invalid pointer error is raised!!
Even with all pointers disposed, MyRecPtr
still points to somewhere in memory, and Node.Data
too!
object pointers delphi-7 new-operator dispose
add a comment |
I use Delphi 7. I create a record that stores info, and using pointers I store that record as an object in a TreeView with more than 100 items.
My problem is, how to release or eliminate all these objects from memory?
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;
How I try to delete them all:
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;
When I delete all items in the TreeView OnDelete
event, I have this:
if assigned(Node.Data) then
begin
Dispose(Node.Data);
end;
What I want to do is release all objects from memory!
If I dispose all objects using that list then if I delete any item from the TreeView an invalid pointer error is raised!!
Even with all pointers disposed, MyRecPtr
still points to somewhere in memory, and Node.Data
too!
object pointers delphi-7 new-operator dispose
You clearly do not understand how pointers and object ownership work. You need to stop what you are doing and go back to basics.
– Remy Lebeau
Jan 2 at 0:40
so if i use this code is enought to release from memory all obects stored in treeviw? : procedure TForm1.Tree1Deletion(Sender: TObject; Node: TTreeNode); begin if Assigned(Node.Data) then Dispose(PMyRec(Node.Data)); end;
– ZinkPT
Jan 2 at 13:13
add a comment |
I use Delphi 7. I create a record that stores info, and using pointers I store that record as an object in a TreeView with more than 100 items.
My problem is, how to release or eliminate all these objects from memory?
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;
How I try to delete them all:
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;
When I delete all items in the TreeView OnDelete
event, I have this:
if assigned(Node.Data) then
begin
Dispose(Node.Data);
end;
What I want to do is release all objects from memory!
If I dispose all objects using that list then if I delete any item from the TreeView an invalid pointer error is raised!!
Even with all pointers disposed, MyRecPtr
still points to somewhere in memory, and Node.Data
too!
object pointers delphi-7 new-operator dispose
I use Delphi 7. I create a record that stores info, and using pointers I store that record as an object in a TreeView with more than 100 items.
My problem is, how to release or eliminate all these objects from memory?
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;
How I try to delete them all:
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;
When I delete all items in the TreeView OnDelete
event, I have this:
if assigned(Node.Data) then
begin
Dispose(Node.Data);
end;
What I want to do is release all objects from memory!
If I dispose all objects using that list then if I delete any item from the TreeView an invalid pointer error is raised!!
Even with all pointers disposed, MyRecPtr
still points to somewhere in memory, and Node.Data
too!
object pointers delphi-7 new-operator dispose
object pointers delphi-7 new-operator dispose
edited Jan 2 at 0:36
Remy Lebeau
340k19265459
340k19265459
asked Jan 1 at 23:44


ZinkPTZinkPT
1
1
You clearly do not understand how pointers and object ownership work. You need to stop what you are doing and go back to basics.
– Remy Lebeau
Jan 2 at 0:40
so if i use this code is enought to release from memory all obects stored in treeviw? : procedure TForm1.Tree1Deletion(Sender: TObject; Node: TTreeNode); begin if Assigned(Node.Data) then Dispose(PMyRec(Node.Data)); end;
– ZinkPT
Jan 2 at 13:13
add a comment |
You clearly do not understand how pointers and object ownership work. You need to stop what you are doing and go back to basics.
– Remy Lebeau
Jan 2 at 0:40
so if i use this code is enought to release from memory all obects stored in treeviw? : procedure TForm1.Tree1Deletion(Sender: TObject; Node: TTreeNode); begin if Assigned(Node.Data) then Dispose(PMyRec(Node.Data)); end;
– ZinkPT
Jan 2 at 13:13
You clearly do not understand how pointers and object ownership work. You need to stop what you are doing and go back to basics.
– Remy Lebeau
Jan 2 at 0:40
You clearly do not understand how pointers and object ownership work. You need to stop what you are doing and go back to basics.
– Remy Lebeau
Jan 2 at 0:40
so if i use this code is enought to release from memory all obects stored in treeviw? : procedure TForm1.Tree1Deletion(Sender: TObject; Node: TTreeNode); begin if Assigned(Node.Data) then Dispose(PMyRec(Node.Data)); end;
– ZinkPT
Jan 2 at 13:13
so if i use this code is enought to release from memory all obects stored in treeviw? : procedure TForm1.Tree1Deletion(Sender: TObject; Node: TTreeNode); begin if Assigned(Node.Data) then Dispose(PMyRec(Node.Data)); end;
– ZinkPT
Jan 2 at 13:13
add a comment |
1 Answer
1
active
oldest
votes
Your code is crashing because you are freeing the same memory twice, because you have not defined any clear ownership of your record instances.
Your ListaDePonteiros
and ListaDeObjectos
lists are redundant and can be removed. The TTreeView
can be the owner of the records and you can simply Dispose()
of them in the TTreeView.OnDeletion
event and be done with it 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;
Otherwise, if you choose to keep a separate list, keep the ListaDeObjectos
list and remove the ListaDePonteiros
list (as there is no reason to maintain 2 lists tracking the exact same values). You would just need to decide whether you want ListaDeObjectos
or Tree1
to own the records you allocate:
If
ListaDeObjectos
is to be the owner, DO NOT callDispose(Node.Data)
in theTTreeView.OnDeletion
event.
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;
If
Tree1
is to be the owner, DO NOT callDispose(AList.Items[intContador])
inEmptyTList()
(in fact, you can get rid ofEmptyTList()
altogether and just callListaDeObjectos.Clear()
when needed).
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;
Either way, when not mass-clearing Tree1
and ListaDeObjectos
in one go, consider calling ListaDeObjectos.Remove()
in the TTreeView.OnDeletion
event to keep Tree1
and ListaDeObjectos
in sync when removing individual nodes:
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. Whenever you do Dispose()
your record instance, make sure you type-cast raw pointers to PMyRec
or else the compiler will not finalize the record's members correctly, leaking memory.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53999815%2fhow-to-release-objects-stored-in-a-treeview-from-memory%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your code is crashing because you are freeing the same memory twice, because you have not defined any clear ownership of your record instances.
Your ListaDePonteiros
and ListaDeObjectos
lists are redundant and can be removed. The TTreeView
can be the owner of the records and you can simply Dispose()
of them in the TTreeView.OnDeletion
event and be done with it 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;
Otherwise, if you choose to keep a separate list, keep the ListaDeObjectos
list and remove the ListaDePonteiros
list (as there is no reason to maintain 2 lists tracking the exact same values). You would just need to decide whether you want ListaDeObjectos
or Tree1
to own the records you allocate:
If
ListaDeObjectos
is to be the owner, DO NOT callDispose(Node.Data)
in theTTreeView.OnDeletion
event.
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;
If
Tree1
is to be the owner, DO NOT callDispose(AList.Items[intContador])
inEmptyTList()
(in fact, you can get rid ofEmptyTList()
altogether and just callListaDeObjectos.Clear()
when needed).
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;
Either way, when not mass-clearing Tree1
and ListaDeObjectos
in one go, consider calling ListaDeObjectos.Remove()
in the TTreeView.OnDeletion
event to keep Tree1
and ListaDeObjectos
in sync when removing individual nodes:
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. Whenever you do Dispose()
your record instance, make sure you type-cast raw pointers to PMyRec
or else the compiler will not finalize the record's members correctly, leaking memory.
add a comment |
Your code is crashing because you are freeing the same memory twice, because you have not defined any clear ownership of your record instances.
Your ListaDePonteiros
and ListaDeObjectos
lists are redundant and can be removed. The TTreeView
can be the owner of the records and you can simply Dispose()
of them in the TTreeView.OnDeletion
event and be done with it 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;
Otherwise, if you choose to keep a separate list, keep the ListaDeObjectos
list and remove the ListaDePonteiros
list (as there is no reason to maintain 2 lists tracking the exact same values). You would just need to decide whether you want ListaDeObjectos
or Tree1
to own the records you allocate:
If
ListaDeObjectos
is to be the owner, DO NOT callDispose(Node.Data)
in theTTreeView.OnDeletion
event.
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;
If
Tree1
is to be the owner, DO NOT callDispose(AList.Items[intContador])
inEmptyTList()
(in fact, you can get rid ofEmptyTList()
altogether and just callListaDeObjectos.Clear()
when needed).
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;
Either way, when not mass-clearing Tree1
and ListaDeObjectos
in one go, consider calling ListaDeObjectos.Remove()
in the TTreeView.OnDeletion
event to keep Tree1
and ListaDeObjectos
in sync when removing individual nodes:
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. Whenever you do Dispose()
your record instance, make sure you type-cast raw pointers to PMyRec
or else the compiler will not finalize the record's members correctly, leaking memory.
add a comment |
Your code is crashing because you are freeing the same memory twice, because you have not defined any clear ownership of your record instances.
Your ListaDePonteiros
and ListaDeObjectos
lists are redundant and can be removed. The TTreeView
can be the owner of the records and you can simply Dispose()
of them in the TTreeView.OnDeletion
event and be done with it 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;
Otherwise, if you choose to keep a separate list, keep the ListaDeObjectos
list and remove the ListaDePonteiros
list (as there is no reason to maintain 2 lists tracking the exact same values). You would just need to decide whether you want ListaDeObjectos
or Tree1
to own the records you allocate:
If
ListaDeObjectos
is to be the owner, DO NOT callDispose(Node.Data)
in theTTreeView.OnDeletion
event.
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;
If
Tree1
is to be the owner, DO NOT callDispose(AList.Items[intContador])
inEmptyTList()
(in fact, you can get rid ofEmptyTList()
altogether and just callListaDeObjectos.Clear()
when needed).
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;
Either way, when not mass-clearing Tree1
and ListaDeObjectos
in one go, consider calling ListaDeObjectos.Remove()
in the TTreeView.OnDeletion
event to keep Tree1
and ListaDeObjectos
in sync when removing individual nodes:
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. Whenever you do Dispose()
your record instance, make sure you type-cast raw pointers to PMyRec
or else the compiler will not finalize the record's members correctly, leaking memory.
Your code is crashing because you are freeing the same memory twice, because you have not defined any clear ownership of your record instances.
Your ListaDePonteiros
and ListaDeObjectos
lists are redundant and can be removed. The TTreeView
can be the owner of the records and you can simply Dispose()
of them in the TTreeView.OnDeletion
event and be done with it 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;
Otherwise, if you choose to keep a separate list, keep the ListaDeObjectos
list and remove the ListaDePonteiros
list (as there is no reason to maintain 2 lists tracking the exact same values). You would just need to decide whether you want ListaDeObjectos
or Tree1
to own the records you allocate:
If
ListaDeObjectos
is to be the owner, DO NOT callDispose(Node.Data)
in theTTreeView.OnDeletion
event.
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;
If
Tree1
is to be the owner, DO NOT callDispose(AList.Items[intContador])
inEmptyTList()
(in fact, you can get rid ofEmptyTList()
altogether and just callListaDeObjectos.Clear()
when needed).
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;
Either way, when not mass-clearing Tree1
and ListaDeObjectos
in one go, consider calling ListaDeObjectos.Remove()
in the TTreeView.OnDeletion
event to keep Tree1
and ListaDeObjectos
in sync when removing individual nodes:
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. Whenever you do Dispose()
your record instance, make sure you type-cast raw pointers to PMyRec
or else the compiler will not finalize the record's members correctly, leaking memory.
answered Jan 2 at 1:29
Remy LebeauRemy Lebeau
340k19265459
340k19265459
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53999815%2fhow-to-release-objects-stored-in-a-treeview-from-memory%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
You clearly do not understand how pointers and object ownership work. You need to stop what you are doing and go back to basics.
– Remy Lebeau
Jan 2 at 0:40
so if i use this code is enought to release from memory all obects stored in treeviw? : procedure TForm1.Tree1Deletion(Sender: TObject; Node: TTreeNode); begin if Assigned(Node.Data) then Dispose(PMyRec(Node.Data)); end;
– ZinkPT
Jan 2 at 13:13