Link to home
Start Free TrialLog in
Avatar of Stuart_Johnson
Stuart_Johnson

asked on

What's the best way of doing this?

We have some old code which is possibly causing us headache.  We keep getting access violations all the time, and I can't work out where the problem starts.

The person who originally wrote the code did things a little differently to what I'm used to, and I'm trying to work out if this is OK or not.

The form is dynamically created:

MktForm := MktForm.Create(Self);
MktForm.ShowModal;

in MktForm, this is done:

FormClose
  Action := caFree;

FormDestroy
  MktForm := nil;

Is this OK to do?  Is instructing the Action to free the form on close, plus setting it to Nil in the FormDestroy allowed?

I can't trace the source to where the A/V occurs.  It's annoying the hell out of me.  It only happens sometimes (when a certain sequence of clicks is made).  So I'm trying to find all dynamically created objects and make sure they're all freed.  There are a lot of them, but the majority aren't called in most circumstances so it's not causing my general problem.

Any help would be appreciated.

Stu
Avatar of kretzschmar
kretzschmar
Flag of Germany image

the nil in formdestroy is not a good choice
Avatar of Motaz
Motaz

When you create any component at run-time and you assign an owner for it, the owner (Form for example) will destroy it when the owner destroyed, so that if the owner find that this component is already destroyed or assigned to nil, an access violation some times occure.

until now, I didn't find a solution for this problem, so that I lave such components without destorying and let thier owner to destroy it.

Motaz
my usual way:

  MktForm := MktForm.Create(nil);
  try
    if MktForm.ShowModal = mrOK then
    begin
       // do something here
    end;
  finally
   MktForm.Release;
   // if you have to access MktForm variable from another part of your application
   // and be sure that it is initialized or not (checking nil) then
   // uncomment line bellow
   // MktForm := nil;
  end;

------
Igor.


with MktForm.Create(Self) do
  try
    if ShowModal = mrOK then
    begin
       // do something here
    end;
  finally
    Free;
  end;

That is my way of doing it.
I also delete the global variable from MktForm.
I never had a problem with Free for the form.

>> MktForm := MktForm.Create(nil);
must be:
MktForm := TMktForm.Create(nil);

 >> with MktForm.Create(Self) do
the same error
with TMktForm.Create(Self) do

btw, Release is preferable. I had problems with Free and it was solved regarding Release.


----
Igor
ASKER CERTIFIED SOLUTION
Avatar of AvonWyss
AvonWyss
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Robert, free problem is not always occured, I use it for long time in my graduation project while I was developing it, and every thing working fine, in the discussion day it rais access violation when I close my project, and that was the first time, so that you can not be sure if freeing owned component manually safe or not.

Motaz
I've experienced the same problems and this worked for me:

1. Change the 'Self' into 'Application'
2. Make sure that every form is in the 'available form'-section instead of the 'autocreate form'-section.

There is some code from my program:

type
  TfrmMinCost = class(TForm)
    . . .
  private
    . . .
  public
    . . .
  end;

procedure ShowMinCostForm;

var
  frmMinCost: TfrmMinCost;

implementation

{$R *.DFM}

procedure ShowMinCostForm;
begin
 try
   if not Assigned(frmMinCost) then
     Application.CreateForm(TfrmMinCost,frmMinCost);
   if frmMinCost.ShowModal = mrOK then
    begin
      . . .
    end;
 finally
   frmMinCost.Free;
   frmMinCost:=nil;
 end;
end;
    . . .

end.


Remove this form from Project->Options->Forms Auto-create list.
In my experience you could set the OnCreate event handler to:

Action = caFree;

This makes the memory being freed without problems.
Check your modules for not disconnecting connections, such as Socket, HTTP or data access components.
Close all DataSets, before closing forms or application.
Avatar of Stuart_Johnson

ASKER

Hi Folks,

Sorry for the length of time it's taken for me to post anything.  All your comments are great and very helpful.  Most of what you have said I already do - remember the code I posted above was someone elses.

What I usually do is never have any forms auto created (except the main form).  I then create the forms, but I always use nil as the  owner - unless the form is an MDI child.  I always free the form using FormName.Free:

  MyForm := TMyForm.Create(nil);
  try
    MyForm.ShowModal;
  finally
    MyForm.Free;
  end;

I never have problems with it.

I just wanted clarification that what was done above wasn't really advisable.  The guy who coded our app originally was a dreadful programmer.  His code is the worst I've seen (even our 1st year juniors code better than him).

I'll have a good read through what's posted in the morning (as it's fairly late here now and I want to get home).  I'll ask for more info if I need it, or award some points.

Thanks again,


Stu
Meikl,

You said "the nil in formdestroy is not a good choice".  

Can you tell me why?

Our app is MDI.  We check to see what forms are opened using if FormName <> nil then do....

If we don't say FormName := nil; in the FormDestroy, FormName is always assigned "something", so testing for nil doesn't work.

AvonWyss:

I love that memory checking utility!  Thanks for the link.

thegroup:

AFAIK FormCreate doesn't have an action property, but FormClose does.

oraelbis:

All datasets are closed before the form is closed.  We don't have anything else which could cause problems that we know of (no socket components or stuff expecting data).

Although AvonWyss didn't directly answer the question, he did give me some great tips and a very useful application.  The points are yours.

Thanks to everyone for your help and input.  I really appreciate it.

Stu
Stuart, thank you!  Have a nice weekend.
No problems at all!  You have a great weekend too!

Stu