在另一个窗体的 OnDestroy 事件中释放窗体时发生访问冲突
Access violation while freeing a form in another form's OnDestroy event
我正在处理 Delphi 7。我在释放表单时遇到访问冲突错误。
1) 创建新应用程序 Delphi 7 (Unit1)
2) 添加新表格 (Unit2)
3) 对于 Unit1 使用子句添加 Unit2 并编写下面的代码
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) 运行 应用程序并关闭 Form1 -- 出现以下错误。
我不想在 OnClose 或 OnCloseQuery 上释放 Form2 对象,因为我在这些上有一些代码events.I想在 OnClose 或 OnCloseQuery 后释放 Form2 对象。
为什么我会收到错误信息以及如何解决这个问题?
问题是 Form2
将在 unit2
中声明,并再次在此表单的 FormCreate 中声明。你只是用错了。
我建议把unit2的Form2
的声明去掉,只用本单元的那个,同时把声明移到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;
您描述的问题可以在 Delphi 7 中重现,按照您的步骤操作。访问冲突的原因是 Form2
是在 .dpr
文件中自动创建的(这使应用程序成为表单的所有者),但您还试图通过调用 [=13= 来控制其生命周期] 在 Form1
的 OnDestroy
事件中。当您尝试释放表单时,应用程序已将其释放。
不太清楚,为什么当应用程序(大概)即将终止(因为主窗体正在被销毁)时,您试图释放 Form2
。由于应用程序是所有者,您可以安全地让应用程序处理它的职责。
您需要决定,您希望谁成为 Form2
的所有者。
- 如果是你,你应该从自动创建的表单列表中删除
Form2
(请参阅 Project - Options - Forms
并将 Form2
移至 Available forms
)。
- 如果您希望应用程序成为所有者,只需不要
Free
表单,如果需要,使用 hide
和 show
方法来控制其可见性,但离开它交给应用程序根据其设计销毁它。
顺便说一句,您在TForm1.FormCreate()
中的代码与您看到的AV无关。那Form2
是一个单独的实例,如果本意是为了展示一个splash形式,也可以,如下:
procedure TForm1.FormCreate(Sender: TObject);
var
form2 : TForm2;
begin
form2 := TForm2.Create(nil);
try
form2.ShowModal;
finally
form2.Free;
end;
end;
表单不需要所有者,因此 Create
中的 nil
。由于变量 form2
是本地变量,因此绝对没有必要将其设为 nil。
我正在处理 Delphi 7。我在释放表单时遇到访问冲突错误。
1) 创建新应用程序 Delphi 7 (Unit1)
2) 添加新表格 (Unit2)
3) 对于 Unit1 使用子句添加 Unit2 并编写下面的代码
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) 运行 应用程序并关闭 Form1 -- 出现以下错误。
我不想在 OnClose 或 OnCloseQuery 上释放 Form2 对象,因为我在这些上有一些代码events.I想在 OnClose 或 OnCloseQuery 后释放 Form2 对象。
为什么我会收到错误信息以及如何解决这个问题?
问题是 Form2
将在 unit2
中声明,并再次在此表单的 FormCreate 中声明。你只是用错了。
我建议把unit2的Form2
的声明去掉,只用本单元的那个,同时把声明移到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;
您描述的问题可以在 Delphi 7 中重现,按照您的步骤操作。访问冲突的原因是 Form2
是在 .dpr
文件中自动创建的(这使应用程序成为表单的所有者),但您还试图通过调用 [=13= 来控制其生命周期] 在 Form1
的 OnDestroy
事件中。当您尝试释放表单时,应用程序已将其释放。
不太清楚,为什么当应用程序(大概)即将终止(因为主窗体正在被销毁)时,您试图释放 Form2
。由于应用程序是所有者,您可以安全地让应用程序处理它的职责。
您需要决定,您希望谁成为 Form2
的所有者。
- 如果是你,你应该从自动创建的表单列表中删除
Form2
(请参阅Project - Options - Forms
并将Form2
移至Available forms
)。 - 如果您希望应用程序成为所有者,只需不要
Free
表单,如果需要,使用hide
和show
方法来控制其可见性,但离开它交给应用程序根据其设计销毁它。
顺便说一句,您在TForm1.FormCreate()
中的代码与您看到的AV无关。那Form2
是一个单独的实例,如果本意是为了展示一个splash形式,也可以,如下:
procedure TForm1.FormCreate(Sender: TObject);
var
form2 : TForm2;
begin
form2 := TForm2.Create(nil);
try
form2.ShowModal;
finally
form2.Free;
end;
end;
表单不需要所有者,因此 Create
中的 nil
。由于变量 form2
是本地变量,因此绝对没有必要将其设为 nil。