How to release Objects stored in a TreeView from memory?












-1















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!










share|improve this question

























  • 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


















-1















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!










share|improve this question

























  • 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
















-1












-1








-1








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!










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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





















  • 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














1 Answer
1






active

oldest

votes


















1














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 call Dispose(Node.Data) in the TTreeView.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 call Dispose(AList.Items[intContador]) in EmptyTList() (in fact, you can get rid of EmptyTList() altogether and just call ListaDeObjectos.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.






share|improve this answer























    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
    });


    }
    });














    draft saved

    draft discarded


















    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









    1














    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 call Dispose(Node.Data) in the TTreeView.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 call Dispose(AList.Items[intContador]) in EmptyTList() (in fact, you can get rid of EmptyTList() altogether and just call ListaDeObjectos.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.






    share|improve this answer




























      1














      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 call Dispose(Node.Data) in the TTreeView.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 call Dispose(AList.Items[intContador]) in EmptyTList() (in fact, you can get rid of EmptyTList() altogether and just call ListaDeObjectos.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.






      share|improve this answer


























        1












        1








        1







        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 call Dispose(Node.Data) in the TTreeView.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 call Dispose(AList.Items[intContador]) in EmptyTList() (in fact, you can get rid of EmptyTList() altogether and just call ListaDeObjectos.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.






        share|improve this answer













        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 call Dispose(Node.Data) in the TTreeView.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 call Dispose(AList.Items[intContador]) in EmptyTList() (in fact, you can get rid of EmptyTList() altogether and just call ListaDeObjectos.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.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 2 at 1:29









        Remy LebeauRemy Lebeau

        340k19265459




        340k19265459
































            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            How to fix TextFormField cause rebuild widget in Flutter

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith