RaelB 4 Posted February 11, 2023 I create a number of Frames and store them in a Frame Object List (declared as FFrames: TObjectList<TMyFrame>) The frames are also added to the VCL form. I try to replace a Frame with below code, but it results in an "Invalid Pointer Operation": (I'm replacing the last Frame in the list with a new one) procedure TForm1.btnReplaceClick(Sender: TObject); var NewFrame: TMyFrame; OldFrame: TMyFrame; begin if FFrames.Count = 0 then exit; NewFrame := GetNewFrame; OldFrame := FFrames[FFrames.Count - 1]; FFrames[FFrames.Count - 1] := NewFrame; OldFrame.Free; end; What's wrong with the code? Full code follows: unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Generics.Collections, MyFrameU; type TForm1 = class(TForm) ScrollBox1: TScrollBox; btnAdd: TButton; btnReplace: TButton; procedure btnAddClick(Sender: TObject); procedure btnReplaceClick(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } FFrames: TObjectList<TMyFrame>; function GetNewFrame: TMyFrame; public { Public declarations } end; var Form1: TForm1; Counter: Integer; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin FFrames := TObjectList<TMyFrame>.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin FFrames.Free; end; function TForm1.GetNewFrame: TMyFrame; begin Result := TMyFrame.Create(Self); Result.Name := 'MyFrame' + Counter.ToString; Result.Parent := ScrollBox1; Result.Align := alLeft; Result.SetName(Result.Name); Inc(Counter); end; procedure TForm1.btnAddClick(Sender: TObject); var Frame: TMyFrame; begin Frame := GetNewFrame; FFrames.Add(Frame); end; procedure TForm1.btnReplaceClick(Sender: TObject); var NewFrame: TMyFrame; OldFrame: TMyFrame; begin if FFrames.Count = 0 then exit; NewFrame := GetNewFrame; OldFrame := FFrames[FFrames.Count - 1]; FFrames[FFrames.Count - 1] := NewFrame; OldFrame.Free; end; end. Share this post Link to post
Alexander Sviridenkov 357 Posted February 11, 2023 By default TObjectList owns contained objects. So create it with False parameter in constructor or use Extract to remove object from list. Share this post Link to post
RaelB 4 Posted February 11, 2023 (edited) Thanks - didn't realise it would affect the operation I was doing. Edited February 11, 2023 by RaelB Share this post Link to post
RaelB 4 Posted February 12, 2023 So, if I keep OwnObjects True, I can just call: FFrames[FFrames.Count - 1] := GetNewFrame; I don't need to worry about Freeing the previous object. 1 Share this post Link to post
programmerdelphi2k 237 Posted February 12, 2023 by doing it this way, you're saying something like this: ob1 now you're obj2... so wouldn't it be more correct for you to "remove obj1" and "add obj2"? see procedure "Remove()" and "Add()" from the list. if the list is not the "owner" of the object then you will need to release it from memory to avoid memory leak Share this post Link to post
RaelB 4 Posted February 12, 2023 Quote you're saying something like this: ob1 now you're obj2... Well no. We're not saying ob1 is now obj2. The ObjectList is pointing to one object, then pointing to a different object. And when you make that change, it automatically frees the first object. This I didn't know before.. 🙂 Share this post Link to post
programmerdelphi2k 237 Posted February 12, 2023 then, the obj1 not more exists not? it was removed not? (implicitly) Share this post Link to post
David Heffernan 2345 Posted February 13, 2023 13 hours ago, programmerdelphi2k said: wouldn't it be more correct for you to "remove obj1" and "add obj2"? see procedure "Remove()" and "Add()" from the list No. 13 hours ago, programmerdelphi2k said: if the list is not the "owner" of the object then you will need to release it from memory to avoid memory leak When OwnsObjects is true, as it is here, the list is the owner. Share this post Link to post
David Heffernan 2345 Posted February 13, 2023 18 hours ago, RaelB said: So, if I keep OwnObjects True, I can just call: FFrames[FFrames.Count - 1] := GetNewFrame; I don't need to worry about Freeing the previous object. Yes. Share this post Link to post
Remy Lebeau 1394 Posted February 13, 2023 On 2/11/2023 at 3:10 PM, Alexander Sviridenkov said: By default TObjectList owns contained objects. So create it with False parameter in constructor or use Extract to remove object from list. Or, use TList<TMyFrame> instead, which doesn't try to own objects. Share this post Link to post