Hallo Bryan
BS> I recently had a (Delphi 1) problem - the program GPF'ed whenever
BS> it exited. Debugging revealed that the problem lay in the area of a
BS> FontDialog. The program had a TFont variable named BodyFont which
BS> was created by the Form's FormCreate handler and freed by the
BS> Form's FormDestroy handler. [...]
BS> BodyFont.Assign(FontDialog.Font) ;
BS> might be more appropriate. Happily, this fixed the problem. Sadly,
BS> this use of an object's "Assign" method is very poorly documented.
BS> Can anybody provide some insight into what is going on here ?
You know too much and you know too little. That's where trouble starts :-).
First, you acknowledge the difference between deep and undeep copies of
objects. That's good. Using the assignment operator := creates an undeep
copy. In
Font2 := Font1
Font2 (a 4-byte pointer) gets the same value as Font1, meaning it will now
point to the same instance of the font object Font1 points to. This one font
object can now be referenced through both font1 and font2 variables. This
will hardly ever be usefull but in having objects as actual parameter. There
will be no harm done though, unless there already was an instance Font2 (due
to a previous Font2 := TFont.Create ), in which case Font2 would be
orphaned. The old Font2 would then occupy memory and you would not be able to
free it anymore since nowone knows where the instance is located.
The assign _method_ always creates a deep copy. Not the object pointer is
copied, but all of the object's data is copied over the other object's data.
For this to be possible, there must be two different instances of the object
before you use this method. If Font2 was not created before you do
Font2.Assign(Font1);
you are likely to get some sort of system error because Font2 does not point
to a valid TFont object. Instead, it will be nil or point to some random
location in memory. That location will most likely not be granted to your
application to have it's way with, and if it would be by chance, you would
overwrite some of your own code or data which would be trouble just the same.
So much you seemed to understand. So, what really happened was that your
BodyFont was really the same instance as the font dialog's font property.
This could still be fine, BUT YOU MUST NOT DESTROY THAT INSTANCE! When your
program terminates, all objects are destroyed, meaning all Destroy methods of
all objects are called. The font dialog will clean up it's internals,
including it's font property. By the time it calls the Destroy or Free method
of that font property, there will no font property anymore because YOU
destroyed it earlier! ===> GPF
A similar problem arises when we want to "clean up" components we created. A
component's Create method takes one parameter, being the owner of the created
component. Being the neat nerts that we are, we tend to clean up everything
we created. However, every component tries to clean up everything it owns
when it is destroyed. ===> GPF When you provide an existing component as
the owner parameter on the creation of a component, you must leave the
inititive to destroy the component to it's owner.
BS> "Under Win32, GDI objects are not shared as are their 16-bit
BS> counterparts. GDI objects are stored in the process's address
BS> space instead of a globally accessible memory block". Is this
BS> relevant to the problem, and to whether it is also a problem in
BS> Delphi 2 ?
This does not seem to be an issue in this case.
Groeten, Martin.
--- FMail/386 1.02
---------------
* Origin: -=[ E-mail: m_maat@knoware.nl .......... ]=- (2:286/420.1)
|