Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Strange problem with .Free

Posted on 2004-11-02
18
Medium Priority
?
216 Views
Last Modified: 2010-04-05
I create into my VCL a listView.

constructor TMyVCL.Create( AOwner: TComponent);
.........
FList:=TListView.Create(AOwner);
FList.Parent:=Self;
FList.Visible:=False;
.....
end;

procedure TMyVCL.ShowMe;
begin
  FList.Parent:=GetParentForm(Self); //I wish to show it outside my vcl ( as a drop list of a TComboBox ).
  FList.Visible:=True;
end;

destructor .....
...
 FList.Free; // here get an error;
..
end;

If I create my VCL and not call ShowMe I can close my app very well ( destroy my vcl ). But if I can ShowMe before exit then I get an error message. Look like when I change the parent I can't free my FList.

I try with:
  FList.Parent :=Self; // reset the parent to Self as I declared on constructor;
  FList.Free;

But not succefully :(  What to do ?
0
Comment
Question by:ginsonic
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 4
  • 3
  • +2
18 Comments
 
LVL 7

Expert Comment

by:LRHGuy
ID: 12474845
Once you assigned an "owner" to the listview, that owner becomes responsible for "freeing" the object. So, when your form closes, the object is alread gone before your flist.free executes.

Either, don't call flist.free, or do:

FList:=TListView.Create(nil);   //no owner

and then do the flist.free yourself.

I tested it, and it works.
0
 
LVL 1

Assisted Solution

by:vacerose
vacerose earned 400 total points
ID: 12474879
When you reassign the Parent to the parent of TMyVCL the same process that calls your destructor is calling the destructor of the FList directly.  Your component is no longer responsible for freeing FList.

From Delphi help:

"The Parent property declared in TControl is similar to the Owner property declared in TComponent, in that the Parent of a control frees the control just as the Owner of a component frees that Component."
0
 
LVL 9

Author Comment

by:ginsonic
ID: 12476856
Tested with:
  FList:=TListView.Create(nil);
.......
  FList.Free;//error

Tested with:
  FList.Parent:=Self; // I return to initial Parent
  FList.Free; // still error !?!?

Tested with:
  FList:=TListView.Create(nil);
........
  FList.Parent:=Self; // I return to initial Parent
  FList.Free; // still error !?!?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 7

Expert Comment

by:LRHGuy
ID: 12476901
FList is "dead" in the FormDestroy routine...so you won't be able to assign the parent property either. Also, there's no need to.
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 12476937
Oops...if you'd done:

FList:=tListView.Create(nil);

then

FList.Parent:=Self;
FList.Free;

should work. Here's my code..no errors...


procedure TForm2.FormCreate(Sender: TObject);
begin
  FList:=TListView.Create(nil);
  FList.Parent:=Self;
  FList.Visible:=False;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  flist.parent:=self; //not needed, we're destroying object anyway
  fList.free;
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  FList.Parent:=GetParentForm(Self); //I wish to show it outside my vcl ( as a drop list of a TComboBox ).
  FList.Visible:=True;
end;
0
 
LVL 9

Author Comment

by:ginsonic
ID: 12477045
I think that in your demo Self is the Form himself and GetParentForm(Self) return same object. Or in my case Self is myVCL and GetParentForm(Self) is my form. How you can see in your demo have 2 objects ( form and listview) and in mine have 3 (form,vcl and list). Maybe I don't have right !?
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 12477051
I tried several things and haven't been able to get an error on the free. Maybe if you show a little more code we can find the cause.
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 12477209
Well, if the parent returned by GetParentForm() has been destroyed before you call FList.Parent:=Self (or :=nil), then you may get an error on THAT call...since the parent form is gone. (At least that's what seems to happen here.) As a result, the .Free gives an error. I've been able to create that problem.

You'd have to make sure that FList.Parent:=nil before destorying the new parent.
0
 
LVL 5

Expert Comment

by:paulb1989
ID: 12478337
Maybe try this in the destructor of your component.

if FList.Parent=Self then
  FList.Free;
0
 
LVL 5

Assisted Solution

by:paulb1989
paulb1989 earned 400 total points
ID: 12478391
To LRHGuy:

   I don't see how the form that FList is parented by can have been freed before calling the destructor of TMyVCL, as it is also the parent of the TMyVCL component. The form won't be gone whilst its components are still being freed. However, if FList is parented by the form when the destructor of TMyVCL is called, then FList may have already been freed by the form before TMyVCL.

To ginsonic:
   If my code above doesnt work, try this.

   if Assigned(FList) then
     FList.Free;

   I have tested neither of them, so I'm not sure.
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 12478654
Remember that FList can point to memory even if it has been freed.

if you do:

FList:=tListView.Create(nil);
FList.Free;

Then

if Assigned(FList) is TRUE even though the memory has been freed.
0
 
LVL 7

Accepted Solution

by:
LRHGuy earned 800 total points
ID: 12478779
Here's my test code. It works without errors...


type
  Myvcl=class(tcombobox)
    constructor Create(aOwner:tcomponent); override;
    destructor destroy; override;
    procedure ShowIt;
    procedure HideIt;
  private
    FList:tlistview;
  end;

type
  TForm2 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    fMY:MyVcl;
  end;

implementation

{$R *.dfm}

{ Myvcl }

constructor Myvcl.Create(aOwner: tcomponent);
begin
  inherited;
  FList:=TListView.Create(Self);
  FList.Parent:=Self;
  FList.Visible:=False;
  FList.Top:=Height;
end;

destructor Myvcl.destroy;
begin
  {FList is freed automatically}
  inherited;
end;

procedure Myvcl.HideIt;
begin
  FList.Visible:=False;
end;

procedure Myvcl.ShowIt;
begin
  FList.Parent:=GetParentForm(Self);
  FList.Visible:=True;
end;

{TForm2}

procedure TForm2.FormCreate(Sender: TObject);
begin
  fMY:=Myvcl.create(Self);
  fMY.parent:=self;
  fMY.top:=30;
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  fMy.showit;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  fMY.HideIt;
end;
0
 
LVL 9

Author Comment

by:ginsonic
ID: 12480282
On this moment I use same idea. No FList.Free, but not sure if is freed automatically.
0
 
LVL 17

Assisted Solution

by:geobul
geobul earned 400 total points
ID: 12481228
Hi,

Try with the following destructor:

destructor TMyVCL.Destroy;
var c: TComponent;
begin
  if Assigned(FList) then begin
    FList.Parent := nil;
    c := FList.Owner;
    if Assigned(c) then c.RemoveComponent(FList);
    FList.Free;
  end;
  inherited;
end;

Regards, Geo
0
 
LVL 17

Expert Comment

by:geobul
ID: 12481368
You ARE obliged to free FList in any case. Just imagine that your TMyVCL has been created without an owner (i.e. nil). Who will be responsible for freeing FList then?
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 12482393
Regardless of MyVCL has an owner, FList is owned by MyVCL, so if MyVCL is freed, so will FList.

Also, if the object assigned to FList is freed by it's owner (which is usually the case) then the object pointer to by FList is gone, by FList still points to it's memory, hence Assigned(FList) returns true (it is assigned) but FList points to already releases memory.

In Summary,

if you, in Create():
  FList:=tlistview.create(nil);
then you must, in Destroy():
  FList.Free;

if you, in Create():
  FList.tlistview.create(self);
then you should not, in Destroy():
  FList.Free
since the owner will handle it automatically.
0
 
LVL 9

Author Comment

by:ginsonic
ID: 12935197
Thanks for support and HAPPY NEW YEAR!
0
 
LVL 17

Expert Comment

by:geobul
ID: 12938274
Happy New Year to all of you ! Wish you all the best, good health, luck and love :-)
0

Featured Post

Enroll in October's Free Course of the Month

Do you work with and analyze data? Enroll in October's Course of the Month for 7+ hours of SQL training, allowing you to quickly and efficiently store or retrieve data. It's free for Premium Members, Team Accounts, and Qualified Experts!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
Suggested Courses

610 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question