Board index » cppbuilder » create TForm descendant object but delete or not ?

create TForm descendant object but delete or not ?


2006-01-25 02:54:05 AM
cppbuilder83
Using BCB5,
1. When I (during design time) create a second form and set in the project
options to NOT auto-create it,
and when I create the form during run time in the constructor of the main
form like this :
TProperties *Properties = new TProperties(Application) ;
Do I need to delete the pointer in de destructor ?
The help file suggests I shouldn't :
Pass a single Component as a parameter to provide the form with an Owner
(usually the application) that is responsible for freeing it.
This is the most commonly used constructor syntax.
2. I'm asking because in fact I have always deleted myself without seeing
issues at all, but after reading this help section I'm confused.
Important detail perhaps, also different from what I read in the help file,
I actually use the main form's pointer as owner, not application.
So in fact I do this in the constructor :
TProperties *Properties = new TProperties(this) ;
Is using "this" ok instead of "Application" ? And does it influence whether
I need to "manually" delete the pointer or not ?
4. Another important detail and I don't know if it matters in this. I have
not added the other form to the project manager. I just make sure the path
is available in the project options and there are includes to the h and cpp
file.
3. Is how this all is handled different in BCB5 and BDS2006 ? As my
colleague seems to have issues with this (not the same code).
When he does this :
TProperties *Properties = new TProperties(Application) ;
and tries to delete in the destructor, the program crashes on delete.
 
 

Re:create TForm descendant object but delete or not ?

"Peter" < XXXX@XXXXX.COM >wrote in
message news:43d6771a$ XXXX@XXXXX.COM ...
Quote
when I create the form during run time in the constructor of
the main form like this :

TProperties *Properties = new TProperties(Application) ;

Do I need to delete the pointer in de destructor ?
Technically no, however it will not harm anything to do so. When a
TComponent-derived object is owned by another TComponent-derived object,
when it is freed it automatically removes itself from its Owner so that the
Owner's destruction will not try to free it again later on. When the Owner
is freed, it automatically frees any components that it still owns.
Since you have provided the 'Application' as the Owner, the form will
automatically be freed when the Application object is freed, unless you free
the form earlier.
Quote
Is using "this" ok instead of "Application" ?
That is perfectly fine. I would recommend that in this situation.
Quote
And does it influence whether I need to "manually" delete the pointer or
not ?
No.
Quote
I have not added the other form to the project manager. I just make sure
the path is available in the project options and there are includes to the
h
and cpp file.
You should not be using #include statements for .cpp files. Add them to the
project instead.
Quote
Is how this all is handled different in BCB5 and BDS2006 ?
No. They behave the same in these regards.
Quote
As my colleague seems to have issues with this (not the same code).
When he does this :
TProperties *Properties = new TProperties(Application) ;
and tries to delete in the destructor, the program crashes on delete.
It is hard to diagnose that without seeing more code.
Gambit
 

Re:create TForm descendant object but delete or not ?

Peter wrote:
Quote
TProperties *Properties = new TProperties(Application) ;

Do I need to delete the pointer in de destructor ?
No. You do not need to free the memory that that pointer points to.
Quote
TProperties *Properties = new TProperties(this) ;

Is using "this" ok instead of "Application" ?
Yes.
Quote
And does it influence whether
I need to "manually" delete the pointer or not ?
No. The memory where the pointer points to will be freed automatically.
Only if you create a form like:
TProperties *Properties = new TProperties(0) ;
you have to free the memory yourself using a delete Properties;.
Quote
4. Another important detail and I don't know if it matters in this. I have
not added the other form to the project manager.
Then the other form will not be linked to your application.
Quote
I just make sure the path
is available in the project options and there are includes to the h and cpp
file.
You should not include a .cpp file there. Is that possible ? How do you
manage to include files in that way ? The only thing you can do there is
indicate directories where the compiler searches for .h files and so.
Quote
3. Is how this all is handled different in BCB5 and BDS2006 ? As my
colleague seems to have issues with this (not the same code).
When he does this :
TProperties *Properties = new TProperties(Application) ;
and tries to delete in the destructor, the program crashes on delete.
In which destructor ? And how ?
Hans.
 

{smallsort}

Re:create TForm descendant object but delete or not ?

Quote
>I just make sure the path is available in the project options and there
>are includes to the h and cpp file.
You should not include a .cpp file there. Is that possible ? How do you
manage to include files in that way ? The only thing you can do there is
indicate directories where the compiler searches for .h files and so.
I meant, set the paths in the options,
do the includes in the main form's h and cpp file.
 

Re:create TForm descendant object but delete or not ?

Quote
3. Is how this all is handled different in BCB5 and BDS2006 ? As my
colleague seems to have issues with this (not the same code).
When he does this :
TProperties *Properties = new TProperties(Application) ;
and tries to delete in the destructor, the program crashes on delete.
In which destructor ?
construction in the main form's constructor.
deletion in the main form's destructor.
Quote
And how ?
delete Properties ;
My colleague let me know that he sees the destructor of the second form
being called before the destructor of the main form (where delete
Properties; is done)
So that appears to be that problem then. "Application" cleans up his second
(manually created) form before the main form is destroyed which causes the
problem in the main form's destructor.
 

Re:create TForm descendant object but delete or not ?

"Peter" < XXXX@XXXXX.COM >wrote in
message news: XXXX@XXXXX.COM ...
Quote
I meant, set the paths in the options,
do the includes in the main form's h and cpp file.
You still have to add the .cpp files to the project in order for the
compiler to process them and the linker to find the compiled symbols.
Otherwise, you are going to have "unresolved external" errors.
Gambit
 

Re:create TForm descendant object but delete or not ?

"Peter" < XXXX@XXXXX.COM >wrote in
message news: XXXX@XXXXX.COM ...
Quote
My colleague let me know that he sees the destructor of the second
form being called before the destructor of the main form (where
delete Properties; is done)
If that is the case, then your main form is trying to delete the Properties
form a second time after it has already been freed. That would explain the
AV your collegue is seeing.
Quote
So that appears to be that problem then. "Application" cleans up his
second (manually created) form before the main form is destroyed which
causes the problem in the main form's destructor.
In all versions of the VCL, owned components are freed in the *reverse*
order than how they are added to their Owner. Your code is adding the main
form to the Application (TForm's constructor handles that) before your
Properties form is added, so the Properties form is freed before the main
form. If you want to be notified about when the Properties form is freed,
call its FreeNotification() method, ie:
TProperties *Properties = NULL;
__fastcall TMainForm::TMainForm(TComponent *Owner)
: TForm(Owner)
{
Properties = new TProperties(Application);
Properties->FreeNotification(this);
}
__fastcall TMainForm::~TMainForm()
{
if( Properties )
delete Properties;
}
void __fastcall TMainForm::Notification(TComponent *AComponent,
TOperation Operation)
{
if( (Operation == opRemove) && (AComponent == Properties) )
Properties = NULL;
}
Gambit
 

Re:create TForm descendant object but delete or not ?

Quote

>I meant, set the paths in the options,
>do the includes in the main form's h and cpp file.

You still have to add the .cpp files to the project in order for the
compiler to process them and the linker to find the compiled symbols.
Otherwise, you are going to have "unresolved external" errors.

Sorry but I never do that and have no issues really !?
 

Re:create TForm descendant object but delete or not ?

Quote
In all versions of the VCL, owned components are freed in the *reverse*
order than how they are added to their Owner. Your code is adding the
main
form to the Application (TForm's constructor handles that) before your
Properties form is added, so the Properties form is freed before the main
form.
I see.
And this also explains why he (my colleague) and I have different
experiences with this then.
I use the "this" pointer of the main form as owner when I create a new form
(say Properties)
So the main form will clean up Properties only after its own destructor is
executed ?
Right ?
Whereas my colleague uses the "Application" as owner, and so he runs into
the reverse order situation you explained.
 

Re:create TForm descendant object but delete or not ?

Peter wrote:
Quote
>You still have to add the .cpp files to the project in order for the
>compiler to process them and the linker to find the compiled symbols.
>Otherwise, you are going to have "unresolved external" errors.

Sorry but I never do that and have no issues really !?
That is then because you #include .cpp files in other .cpp files.
Those other .cpp files are added to your project.
You will never #include a .cpp file in a .h file. Did you ?
Hans.
 

Re:create TForm descendant object but delete or not ?

"Hans Galema" < XXXX@XXXXX.COM >wrote in message
Quote
Peter wrote:

>>You still have to add the .cpp files to the project in order for the
>>compiler to process them and the linker to find the compiled symbols.
>>Otherwise, you are going to have "unresolved external" errors.
>
>Sorry but I never do that and have no issues really !?

That is then because you #include .cpp files in other .cpp files.
Those other .cpp files are added to your project.
Yes, it ultimately boils down to the main form that is included in the
project.
Quote
You will never #include a .cpp file in a .h file. Did you ?
No, I tend to include the cpp file (e.g. sub form) in the cpp file of the
class that uses the functionality (e.g. main form)
Same for the h file (sub), which is included in the h file (main).
 

Re:create TForm descendant object but delete or not ?

Peter wrote:
Quote
Yes, it ultimately boils down to the main form that is included in the
project.
Why is it so difficult to be precise ? Did you mean that in Project.cpp
you #include Unit1.cpp ?
If so then you should remove that #include statement and add Unit1.cpp
to your project instead. Or did you mean: In Project.cpp I see a statement
like: USEFORM("Unit1.cpp", Form1); ? The latter is correct of course for
a c++builder project.cpp file.
Quote
No, I tend to include the cpp file (e.g. sub form) in the cpp file of the
class that uses the functionality (e.g. main form)
That is a bad habit as far as I can see. Be a good bcb user and add
Unit1.cpp with the projectmanager. In the .cpp file that uses the form in
Unit1.cpp only #include Unit1.h.
Quote
Same for the h file (sub), which is included in the h file (main).
That is correct.
Hans.
 

Re:create TForm descendant object but delete or not ?

"Peter" < XXXX@XXXXX.COM >wrote in
message news:43d7df7a$ XXXX@XXXXX.COM ...
Quote
I use the "this" pointer of the main form as owner when I create
a new form (say Properties)
So the main form will clean up Properties only after its own
destructor is executed ? Right ?
Yes.
Gambit
 

Re:create TForm descendant object but delete or not ?

Quote
Did you mean that in Project.cpp you #include Unit1.cpp ?
That's what I meant yes.
 

Re:create TForm descendant object but delete or not ?

"Peter" < XXXX@XXXXX.COM >wrote in
message news: XXXX@XXXXX.COM ...
Quote
That's what I meant yes.
You should not be doing that at all.
Gambit