Delphi7中在另一窗体OnDestroy事件释放窗体时触发Access violation问题
Delphi 7 释放窗体时 Access Violation 问题解决指南
老兄,我太懂这种在Delphi 7里捣鼓窗体释放时踩AV坑的憋屈感了!结合你给出的复现步骤,这个问题十有八九和窗体生命周期的管理逻辑或者自动创建设置有关,我给你拆解下核心原因和解决办法:
最常见的触发原因
你大概率遇到了「重复释放窗体」的问题:
Delphi默认会把新建的窗体加入自动创建列表,程序启动时VCL会自动实例化这些窗体,退出时又会自动帮你释放。如果你在FormDestroy里又手动调用了Form2.Free,就会导致VCL尝试释放一个已经被销毁的对象,直接触发Access Violation。
分步解决办法
第一步:检查并调整自动创建设置
- 打开菜单栏的
Project -> Options,切换到Forms标签页 - 在
Auto-create forms列表里找Form2,如果存在,选中它并点击箭头移到Available forms列表里 - 点击OK保存设置——这样VCL就不会自动帮你创建和释放Form2了,生命周期完全由你手动控制
第二步:正确的手动创建/释放代码示例
把你的Unit1代码改成下面这种规范写法,避免野指针和重复释放:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Unit2; // 这里引用Unit2没问题 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); begin // 手动创建Form2,Owner设为nil(自己管理释放) Form2 := TForm2.Create(nil); Form2.Show; // 按需用Show或者ShowModal end; procedure TForm1.FormDestroy(Sender: TObject); begin // 释放前先判断对象是否已实例化,避免空指针 if Assigned(Form2) then begin Form2.Free; Form2 := nil; // 释放后置空,彻底避免野指针 end; end; end.
更安全的局部变量写法(推荐)
如果你不需要全局的Form2变量,用局部变量的方式更稳妥,完全避免全局变量带来的生命周期混乱:
// 比如在按钮点击事件里打开Form2 procedure TForm1.Button1Click(Sender: TObject); var frm2: TForm2; // 局部变量,作用域仅限当前方法 begin frm2 := TForm2.Create(Self); // Owner设为Form1,Form1销毁时会自动释放它 try frm2.ShowModal; // 模态显示 finally frm2.Free; // 不管是否异常,都确保释放 end; end;
额外避坑提醒
- 永远不要手动释放「自动创建列表」里的窗体,VCL会帮你处理
- 释放对象后一定要把变量置为
nil,防止后续代码误访问野指针 - 如果给窗体设置了Owner,Owner销毁时会自动释放该窗体,此时不要再手动调用
Free
内容的提问来源于stack exchange,提问作者DelphiLearner
相关产品推荐
相关产品推荐

