Hello,
Sorry I'm on holiday and only noticed this thread now.
Anyway: NEVER free a form in an event handler of the form, as per the
Delphi help. Always use Release instead, which works (IIRC) by posting
a message to the form, and then only freeing it, thus allowing the event
handlers to complete before freeing. (Otherwise, you effectively cut
the branch that you're sitting on from the tree, so to speak...)
Quote from the help:
"Warning: Never explicitly free a component within one of its own
event handlers or the event handler of a component it owns or contains.
For example, don
't free a button, or the form that owns the button, in its OnClick event
handler.
To free a form, call its Release method, which destroys the form and
releases the memory allocated for it after all its event handlers and
those of the components it contains are through executing."
As for handling the auto-freeing/managing the creation/freeing of the
form, you might consider using the following idiom that at least
centralizes the creation of the "default" instance of the form and
removes the responsibility from the rest of your code to continuously
check for and create if required a form before use. I suggest this is
at least preferable to having code all over your app that checks and
creates the form if required.
1.) In the unit of the form, replace the global form variable with a
global accessor/"factory" function. Move the variable the the private
(implementation) part of the unit.
2.) Implement the function so that it checks if the (now private to the
unit global) variable is nil, if so, it creates the form and assigns it
to the variable. The function always returns the value of the variable.
3.) In the destructor of the form (override destroy) or perhaps in the
OnDestroy, check to see if "self" is the same as the global form
variable created by the accessor and is not nil. If so, then the
instance being freed was created by the accessor and is now being freed,
so, then nil the global variable. The next time the accessor is used,
a new instance will now be created. On the other hand, if this instance
was created by some other client code and not by the accessor, then the
references will be different, and we leave the global instance alone,
thus allowing for multiple form instances if that is desired.
4.) In the FormClose event, ensure Action := caFree to ensure forms get
freed when closed.
The benefit is, the global is now effectively read only, due to the
accessor function, so for example buggy code which for example blindly
creates and overwrites the global causing a memory leak is impossible.
Furthermore, no other code has to check the form variable and/or create
the form, it can just be used it and have the form be lazily created on
the fly just before use. If the form is closed, it will be freed (due
to Action = caFree), which in turn will nill the global reference (but
only if the instance being freed is the "global" one.) Nevertheless,
the code will still allow arbitrary client code to declare and create
their own instances of the form if they want to, and such forms will
still be freed when they're closed but won't molest the global reference.
Walter
Jamie L. Mitchell wrote:
>
> Just tried it quickly to make sure I still get the error.
>
> In the OnClose event, I put in code to free the dialog as follows:
>
> frmGlobalPointer := NIL;
> Self.Free;
>
>
[Non-text portions of this message have been removed]
.