F
fishjam
Unregistered / Unconfirmed
GUEST, unregistred user!
在我们开发的系统中,利用接口来实现插件和主程序各个功能模块之间的通信(Exe+Bpl+Dll方法)。于是出现比较奇怪的问题:当程序在结束时,有些窗体的 Destory 中会调用一些接口的方法进行处理,但是这时这些接口已经被释放了(在 finalization 中由Delphi开发环境自动赋nil值释放)。
我的问题就是:form的 Destroy 方法怎么会在 finalization 之后才执行,而各个单元的finalization 顺序又是怎么决定的。
由于代码量比较大,我写了如下的测试代码进行问题测试(不过没有试出Destroy在 finalization 之后执行的情况)。
我的开发环境是Delphi7+Win2KSP4
工程文件:(创建一个两个窗体,一个附加单元的程序)
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' ,
Unit3 in 'Unit3.pas' {Form3};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm3, Form3);
Application.Run;
end.
窗体1程序的主窗体,仅仅用于显示)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CSIntf, StdCtrls;
type
TForm1 = class(TForm)
btn1: TButton;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
end.
单元2(定义接口声明和实现)
unit Unit2;
interface
uses
Classes,Windows,SysUtils;
type
IMyInterface= interface(IUnknown)
procedure Func1;
procedure Func2;
end;
TMyInterfaceObj= class(TInterfacedObject,IMyInterface)
public
FNum:Integer;
procedure Func1;
procedure Func2;
constructor Create;
destructor Destroy;override;
end;
var
Num:Integer;
G_MyInteface:IMyInterface;
implementation
//请注意,如果我把这里的包含Unit3的代码删除,程序就不会出错了
uses
unit3;
constructor TMyInterfaceObj.Create;
begin
inherited Create;
FNum:=Num;
Inc(Num);
OutputDebugString(PChar('TMyInterfaceObj.Create'+IntToStr(FNum)));
end;
destructor TMyInterfaceObj.Destroy;
begin
OutputDebugString(PChar('TMyInterfaceObj.Destroy'+IntToStr(FNum)));
inherited;
end;
procedure TMyInterfaceObj.Func1;
begin
OutputDebugString('TMyInterfaceObj.func1');
end;
procedure TMyInterfaceObj.Func2;
begin
OutputDebugString('TMyInterfaceObj.func2');
end;
initialization
Num:=1;
G_MyInteface:=TMyInterfaceObj.Create
//此处创建全局接口变量
finalization
G_MyInteface:=nil
//此处释放接口变量(如果没有这个语句,Delphi编译器也会自动加上,加上以后可以看出程序流程)
end.
窗体单元3,此处调用全局的接口变量
unit unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,unit2;
type
TForm3 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
procedure TForm3.FormCreate(Sender: TObject);
begin
G_MyInteface.Func1;
end;
procedure TForm3.FormDestroy(Sender: TObject);
begin
G_MyInteface.Func2
//在我们的实际代码中,这个地方会出现访问零地址的错误,不过我的测试代码没有写出这种情况
end;
initialization
G_MyInteface.Func2
//如果在unit2中加入了对unit3的单元引用,这里就会报零地址错误
finalization
G_MyInteface.Func1;
end.
我的问题就是:form的 Destroy 方法怎么会在 finalization 之后才执行,而各个单元的finalization 顺序又是怎么决定的。
由于代码量比较大,我写了如下的测试代码进行问题测试(不过没有试出Destroy在 finalization 之后执行的情况)。
我的开发环境是Delphi7+Win2KSP4
工程文件:(创建一个两个窗体,一个附加单元的程序)
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' ,
Unit3 in 'Unit3.pas' {Form3};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm3, Form3);
Application.Run;
end.
窗体1程序的主窗体,仅仅用于显示)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CSIntf, StdCtrls;
type
TForm1 = class(TForm)
btn1: TButton;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
end.
单元2(定义接口声明和实现)
unit Unit2;
interface
uses
Classes,Windows,SysUtils;
type
IMyInterface= interface(IUnknown)
procedure Func1;
procedure Func2;
end;
TMyInterfaceObj= class(TInterfacedObject,IMyInterface)
public
FNum:Integer;
procedure Func1;
procedure Func2;
constructor Create;
destructor Destroy;override;
end;
var
Num:Integer;
G_MyInteface:IMyInterface;
implementation
//请注意,如果我把这里的包含Unit3的代码删除,程序就不会出错了
uses
unit3;
constructor TMyInterfaceObj.Create;
begin
inherited Create;
FNum:=Num;
Inc(Num);
OutputDebugString(PChar('TMyInterfaceObj.Create'+IntToStr(FNum)));
end;
destructor TMyInterfaceObj.Destroy;
begin
OutputDebugString(PChar('TMyInterfaceObj.Destroy'+IntToStr(FNum)));
inherited;
end;
procedure TMyInterfaceObj.Func1;
begin
OutputDebugString('TMyInterfaceObj.func1');
end;
procedure TMyInterfaceObj.Func2;
begin
OutputDebugString('TMyInterfaceObj.func2');
end;
initialization
Num:=1;
G_MyInteface:=TMyInterfaceObj.Create
//此处创建全局接口变量
finalization
G_MyInteface:=nil
//此处释放接口变量(如果没有这个语句,Delphi编译器也会自动加上,加上以后可以看出程序流程)
end.
窗体单元3,此处调用全局的接口变量
unit unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,unit2;
type
TForm3 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
procedure TForm3.FormCreate(Sender: TObject);
begin
G_MyInteface.Func1;
end;
procedure TForm3.FormDestroy(Sender: TObject);
begin
G_MyInteface.Func2
//在我们的实际代码中,这个地方会出现访问零地址的错误,不过我的测试代码没有写出这种情况
end;
initialization
G_MyInteface.Func2
//如果在unit2中加入了对unit3的单元引用,这里就会报零地址错误
finalization
G_MyInteface.Func1;
end.