Reputation: 489
I am working on Delphi 7. I am getting access violation error while freeing the form.
1) Create new Application Delphi 7 (Unit1)
2) Add new form (Unit2)
3) For Unit1 uses clause add Unit2 and write below code
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, unit2, StdCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
form2 : TForm2;
begin
try
form2 := TForm2.Create(Application);
//form2.ShowModal;
finally
//FreeAndNil(form2);
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Form2 <> nil then
FreeAndNil(form2);
end;
end.
4) Run the Application and close Form1 -- Getting below error.
I don't want to free Form2 Object on OnClose or OnCloseQuery, Because i have some code on these events.I want to free Form2 object after OnClose or OnCloseQuery.
why i am getting error and how to fix this?
Upvotes: 2
Views: 2049
Reputation: 12014
the problem is that Form2
will be declared in unit2
and again in the FormCreate of this form. You are simply using the wrong one.
I suggest removing the declaration of Form2
from unit2 and only use the one in this unit, and also move the declaration to the private section
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
Form2: TForm2; // Declare the form here, not in unit2
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Form2 := TForm2.Create(nil);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
// no need to check if Form2 exists, it is created in the FormCreate and will thus always exist
// unless there is code somewhere that we cant see that destroys it.
// Also no need to set the variable to nil as mentioned in the Tom's answer
Form2.Free;
end;
Upvotes: 3
Reputation: 21033
The problem you describe can be reproduced in Delphi 7, following your steps. The reason for the access violation is that Form2
is autocreated in the .dpr
file (and that makes the application the owner of the form), but you also attempt to control its lifetime by calling FreeAndNil(Form2)
in the OnDestroy
event of Form1
. At the time you attempt to free the form, it is already freed by the application.
It is not really clear, why you attempt to free Form2
when the application (presumably) is about to terminate (since the main form is being destroyed). As the application is the owner you can safely let the application take care of its duties.
You need to decide, who you want to be the owner of Form2
.
Form2
from the list of autocreated forms (see Project - Options - Forms
and move Form2
to Available forms
).Free
the form, use hide
and show
methods to control its visibility, if needed, but leave it to the application to destroy it according its design.By the way, the code you have in TForm1.FormCreate()
has nothing to do with the AV you have seen. That Form2
is a separate instance, and if the intention is to show a splash form, it's ok, as follows:
procedure TForm1.FormCreate(Sender: TObject);
var
form2 : TForm2;
begin
form2 := TForm2.Create(nil);
try
form2.ShowModal;
finally
form2.Free;
end;
end;
The form doesn't need an owner, therefore the nil
in Create
. Since the variable form2
is local, there's absolutely no need to nil it.
Upvotes: 4