TTabControl leaking (?) lazarus / 31-LCL ---------------------------------------------------------------------- chrv · 2021-03-28 11:00 Hi all, Just testing TTabControl. I have to create and destroy tabs and associated objects at runtime. When i free objects Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i for i:=TabControl1.Tabs.Count-1 downto 0 do   TabControl1.Tabs.Objects[i].Free;  it seems tabs captions are destroyed (?) and objects are not (?). At the end : unfreed memory blocks (1 per tab created) When i use similar code with TListBox Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i for i := 0 to ListBox1.Items.Count-1 do    ListBox1.Items.Objects[i].Free; result is as expected. What am i missing ? Here is my complete exemple app. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls  ; type  TMyObject = class(TObject)    OID : integer;  end;  { TForm1 }  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    Button3: TButton;    Button4: TButton;    Edit1: TEdit;    Label1: TLabel;    Label2: TLabel;    Label3: TLabel;    ListBox1: TListBox;    TabControl1: TTabControl;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure Button3Click(Sender: TObject);    procedure Button4Click(Sender: TObject);  private  public  end; var  Form1: TForm1;implementation{$R *.lfm}{ TForm1 }//Creates object and add it to ListBoxprocedure TForm1.Button1Click(Sender: TObject);var  aMyObject : TMyObject;begin  aMyObject := TMyObject.Create;  aMyObject.OID:=Random(20);  ListBox1.AddItem(Edit1.Text,aMyObject);end; //Frees objects. It works OKprocedure TForm1.Button2Click(Sender: TObject);var  i : integer;begin  if ListBox1.Count>0 then  for i := 0 to ListBox1.Items.Count-1 do    ListBox1.Items.Objects[i].Free;  ListBox1.Clear;end; //Creates object and add it to TabControlprocedure TForm1.Button3Click(Sender: TObject);var  aMyObject : TMyObject;begin  aMyObject := TMyObject.Create;  aMyObject.OID:=Random(20);  TabControl1.Tabs.AddObject(Edit1.Text,aMyObject);   Edit1.Text:='';end; //Destroys objects. Does not work as expected : memory leaksprocedure TForm1.Button4Click(Sender: TObject);var  i : integer;begin  if TabControl1.Tabs.Count>0 then  //for i := 0 to TabControl1.Tabs.Count-1 do  //  TabControl1.Tabs.Objects[i].Free;        //<- crash  for i := TabControl1.Tabs.Count-1 downto 0 do    TabControl1.Tabs.Objects[i].Free;  TabControl1.Tabs.Clear;  end;end. ---------------------------------------------------------------------- lucamar · 2021-03-28 11:41 As a general remark, because I don't know if it is relevant here, one shouldn't use the "objects" properties of special TStrings properties (like Tabs here) because it's very posible that they are being used internally by the propety itself. It can be easily ascertained if that is indeed the case with Tabs: add a few in design-mode and check at run-time whether Objects[] is empty or not. ---------------------------------------------------------------------- chrv · 2021-03-28 19:02 @lucamar @jamie Thanks for information. "Objects" is indeed used for another purpose Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 441641044416580044166824 What's the best workaround ? - Not to use Tabs.Objects (of cours) - Copy Tabs (without Objects) to a new TStrings (say "TabsNew") - Store TMyObject to TabsNew.Objects - Always synchronise Tabs with TabsNew Is there a better solution ? ---------------------------------------------------------------------- lucamar · 2021-03-28 19:57 The best, IMHO, is to keep your objects in a separate TStringList and keep it synchronized with Tabs, which basically means responding to adding/deleting a tab and a tab changing its position (e.g. when the user drags a tab to put it before/after another), if this last is allowed in your program. So, yeah, what you outlined seems to be the best solution. Only, remember that TStrings is a quasi-abstract class and that its default implementation is TStringList, so use one of these. ---------------------------------------------------------------------- chrv · 2021-03-28 20:39 That's what i thought. Thanks a lot (see attachment for my implementation)