Freeing components

I create a components at run time such as Memos, labes, and even forms. I make the owner and parent of these component a Form. When I close this form (Not a main form) I free all component that I was created at run-time, but when I close the main form and my application terminated (And when the owner of these component destroyed) Access violation exception alwyas raised.

I think the owner only who must destroy it's components, and when it find it is already destroyed it will rais the exception. In my application I need to destroy that component when I close that form, and I create new ones when I open that form again.

The only thing that I can do now is to assign Visible property of these components to False when I close the form, it works very well but the problem is that will consume memory resource. Is there any safe freeing for such components?

Motaz
www.geocities.com/motaz1
LVL 7
MotazAsked:
Who is Participating?
 
TussinConnect With a Mentor Commented:
I cut this message from delphi help. (topic "TComponent.Create")

For components created manually, that is, not created in the form designer, call Create and pass in an owner componentas the AOwner parameter. The owner will dispose of the component when the owner is destroyed. If the component is not owned, then call Free so that it is destroyed.

That means, all object which inherit from TComponent can be created properly with owner=nil, and you have to call method "Free" by yourself.

you can test on my previous sample.
0
 
EpsylonCommented:
You don't have to free the components on that form. They will be freed automatically when the form is destroyed since the form is their owner.
Btw, use TForm.Release to free the form.
0
 
EpsylonCommented:
You don't have to free the components on that form. They will be freed automatically when the form is destroyed since the form is their owner.
Btw, use TForm.Release to free the form.
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
JaymolCommented:
I get this problem too Motaz.  I usually find that Whatever.Destroy is a little less volatile than .Free, but still has the same problems sometimes.

Worth a try anyway.

John.
0
 
vinnairCommented:
Have you written some code in the formdestroy event or the form close event of the main form as well as the component owner form. If yes, please post that code.
0
 
TussinCommented:
If you want to safe memory, you can create components with owner=nil, So you can free them properly.

Another issue is "don't forget to set all events back to nil".
Normally when you create component at runtime, you often set its event right?
Before free them, set it back to nil first.
0
 
MotazAuthor Commented:
To Tussin
>create components with owner=nil

Can I create Memo without Onwer?

To Vinnair
I write code in OnClose event at the parent form which deletes all created components at run-time.

To Epsylon:
What exactly Realease do? I do not want to lose the parent form, even I do not want to free all it's components, only I need to free some components (which created at run-time)

Motaz
0
 
omeralfarougCommented:
hi
 i don't understand " A componentS" and
"Labes" tell me the meaning and i will answered u.
omeralfaroug
0
 
MotazAuthor Commented:
To Omer:
I mean control components such as Labels and Memos

Azzoz
0
 
florisbCommented:
question is probably answered, but:

write some procedures that you can use to place controls on certain possitions, you could use the tag to be able to find those controls again, or to use one onclick event and check the Sender's tag there. To make this a bit more comfortable, you could add adssociate property's to controls, to be able to fill a list that belongs with a button or something.

Had problems with free's run-time generated controls, too. Tussin: owner nil! Offcourse.

saw this too:
  if assigned(MyRegel.VarControl1) then
      begin
      MyRegel.VarControl1.free;
      MyRegel.VarControl1 := nil;
      end;


procedure placeSomeControl(AParent: TWinControl; x: integer);
var
  CheckboxHaakjeOpen: TUMSAdvancedCheckbox;
  begin
  ///
  checkboxHaakjeOpen := TUMSAdvancedCheckbox.Create(Aparent);
  checkboxHaakjeOpen.parent := Aparent;
  checkboxHaakjeOpen.Left := left1;
  checkboxHaakjeOpen.top := firstspace + ((x - 1) * linespace) + 1;
  checkboxHaakjeOpen.width := checkwidth;
  checkboxHaakjeOpen.Caption := '(';
  checkboxHaakjeOpen.regelnummer := x;
  checkboxHaakjeOpen.enabled := false;
  checkboxHaakjeOpen.checked := true;
  end;

Floris.
0
 
DrDelphiCommented:
Another thing that I am suprised that no-one else mentioned is that you would want to free these controls in the OnCloseQuery event of the form rather than the OnClose. This way you can test to see if all components=nil prior to passing true to the CanClose parameter.
0
 
MotazAuthor Commented:
Is this code can solve my problem:

for i:= 0 to Components.Count - 1 do
  if TControl(Components[i]).Tag = 255 then
begin
  Components[i].Free;
  Components[i]:= nil;
end;

Is that a right code?

0
 
florisbCommented:
I do think so (that's what I posted)... ...but I'm no 'Delphi docter'...:-)

Floris
0
 
TussinCommented:
To Motaz,
   In case that I want dynamic array of component, I normally create component with Owner=nil and free them whenever I want. It works well.
   This is a sample. (don't forget to set event back to nil, otherwise sometimes it will become Access Violation)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

const MAXMEMO=8;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure MemoClick(Sender: TObject);
  private
    { Private declarations }
    MemoList:array[0..MAXMEMO-1] of TMemo;
    MemoCount:Integer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  MemoCount:=0;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if MemoCount=MAXMEMO then
    exit;
  MemoList[MemoCount]:=TMemo.Create(nil);
  with MemoList[MemoCount] do
  begin
    Parent:=Self;
    Left:=MemoCount*40;
    Top:=MemoCount*40;
    OnClick:=MemoClick;
  end;
  Inc(MemoCount);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if MemoCount=0 then
    exit;
  with MemoList[MemoCount-1] do
  begin
    OnClick:=nil;
    Free;
  end;
  Dec(MemoCount);
end;

procedure TForm1.MemoClick(Sender: TObject);
begin
  ShowMessage('Click Click');
end;

end.
0
 
MotazAuthor Commented:
Tussin, what kind of components can I create without having an owner or parent, my componets which cause the problem is Visual components such Lebels, and Memos, so that can I create it without owner or parent?
0
 
MotazAuthor Commented:
Tussin, what about MDI child forms, I think it must has an owner, isn't it?
0
 
TussinCommented:
Normally, all forms is created with owner=Application and will be free before terminate a program.

This is an example of MDIChild form creation.
procedure TMainForm.CreateMDIChild(const Name: string);
var
  Child: TMDIChild;
begin
  { create a new MDI child window }
  Child := TMDIChild.Create(Application);
  Child.Caption := Name;
end;
That means this form will be free automatically when application is terminated.

you can safe memory by using Event OnFormClose.

TForm provides a variable "Action" in OnFormClose event, if you set it to "cafree", it will free itself after close form

procedure TMDIChild.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

Anyway you can create MDIChild windows with Owner=nil.
0
All Courses

From novice to tech pro — start learning today.