0

I have a Form for which I coded my own constructor:

constructor Create(AOwner: TComponent; AParent: TWinControl; ASender: TMyClass;
   ATab: String); reintroduce; overload;

To create such a form I use the following:

try
  MyForm := TMyClassForm.Create(nil, Self.Parent, Self as TMyClass, 'FirstTab');
  MyForm.ShowModal;
finally
  MyForm.Free;
end;

Somewhere else, before starting a procedure, I need to check whether this form is opened or not, so I check its existence with:

if (Assigned(MyForm)) and (MyForm.Active) and (MyForm.Showing) then
  // Don't do the procedure
else
  // Do the procedure

Now, if I open the form and close it, and I check this conditional statement, everytime I get true, but the Form is not opened and not showing anymore, because I freed it after creating.

Any idea of what could be the problem?

pnuts
  • 58,317
  • 11
  • 87
  • 139
Felipe
  • 253
  • 4
  • 11

2 Answers2

5

You called Free on the MyForm global method, but you did not modify the reference. So, MyForm still refers to the now destroyed form. And so Assigned(MyForm) evaluates as True, and then the other two tests operate on the stale object reference. Anything could happen when you operate on a stale object reference. In the situations that you have tried, it seems that the operations both return True. But another time you might get an access violation.

You'll want to set the MyForm variable to nil after call Free. At the risk of re-starting the great religious Delphi war of our times, you might contemplate using FreeAndNil(MyForm) in place of MyForm.Free.

You might find my answer here to be instructive: Why should I not use "if Assigned()" before using or freeing things?

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • It worked perfect, but I expected that Free would make this task of setting the variable to nil... don't see the point of don't doing that. Thanks a lot – Felipe Aug 05 '13 at 14:26
  • Ironic that my linking of http://stackoverflow.com/questions/8548843/why-should-i-not-use-if-assigned-before-using-or-freeing-things/8550628#8550628 led to somebody removing an upvote from that answer. – David Heffernan Aug 05 '13 at 15:12
  • @Felipe: calling Free() does not automatically nil the variable, you have to use FreeAndNil() for that (actually, Free() does nil the variable in the iOS compiler under ARC, but that is an exception to the rule right now). – Remy Lebeau Aug 05 '13 at 15:38
  • @Felipe The answer that I linked to in the final paragraph covers in much detail the exact topic you raise in your comment – David Heffernan Aug 05 '13 at 16:33
1
  1. Init: MyForm := nil;

  2. User FreeAndNil(MyForm)

  3. if (Assigned(MyForm)) then
    DON'T DO THE PROCEDURE
    else
    DO THE PROCEDURE

ZibNimer
  • 9
  • 1