我最近遇到了一些我无法解释的行为,与Delphi接口变量有关.
从本质上讲,它归结为编译器在Broadcast方法中生成的隐式接口变量.
在终止方法的结束语句中,结尾代码包含两个调用IntfClear.其中一个我可以解释,它对应于Listener局部变量.另一个我无法解释,它会TComponent._Release在对象实例被销毁后带你到(调试DCU).它不会产生AV,但这很幸运,并且通过完整的FastMM调试,报告了破坏后实例访问.
这是代码:
program UnexpectedImplicitInterfaceVariable;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
type
IListener = interface
['{6D905909-98F6-442A-974F-9BF5D381108E}']
procedure HandleMessage(Msg: Integer);
end;
TListener = class(TComponent, IListener)
//TComponent._AddRef and TComponent_Release return -1
private
procedure HandleMessage(Msg: Integer);
end;
{ TListener }
procedure TListener.HandleMessage(Msg: Integer);
begin
end;
type
TBroadcaster = class
private
FListeners: IInterfaceList;
FListener: TListener;
public
constructor Create;
procedure Broadcast(Msg: Integer);
end;
constructor TBroadcaster.Create;
begin
inherited;
FListeners := TInterfaceList.Create;
FListener := TListener.Create(nil);
FListeners.Add(FListener);
end;
procedure TBroadcaster.Broadcast(Msg: …Run Code Online (Sandbox Code Playgroud) 我有一个助手类,将在整个应用程序中广泛使用.实现依赖于接口引用计数,这个想法大致是:
...
var
lHelper: IMyHelper;
begin
lHelper := TMyHelper.Create(some params);
...some code that doesn't have to access lHelper
end;
Run Code Online (Sandbox Code Playgroud)
因此,实现依赖于IMyHelper在方法结束时超出范围,但之前没有.
所以我要问的是,我可以肯定,在未来的某些Delphi编译器中,如果在该方法的其余部分中没有访问该变量,那么在创建它之后就不会发挥智能并立即释放界面吗?
我编写了一个Delphi程序,它将单个.XLS文件的几个不同电子表格中的数据提取并合并到一个文本文件中,以便以后处理.这是一个Delphi 7 控制台程序.
最相关的代码段的摘录将向您展示,显然,我的程序表现得非常好,或者至少与它需要的程序一样多.
uses ... ActiveX, ComObj ... ;
procedure Fatal(s:string);
...
Halt(1);
var ExcelApp:Variant; (* global var *)
begin (* main program block *)
coInitialize(nil);
ExcelApp:=CreateOleObject('Excel.Application');
try
ExcelApp.Visible:=False;
ExcelApp.WorkBooks.Open(ExcelFileName);
...
XLSSheet := ExcelApp.Worksheets[ExcelSheetName];
...
try
XLSRange := XLSSheet.Range[ExcelRangeName];
except
Fatal('Range "'+ExcelRangeName+'" not found');
end;
if VarIsNull(XLSRange) then Fatal('Range '+ExcelRangeName+' not found');
for row:=XLSRange.Row to XLSRange.Rows[XLSRange.Rows.Count].Row do
for col:=XLSRange.Column to XLSRange.Columns[XLSRange.Columns.Count].Column do
CellValue:=XLSSheet.Cells[Row,Col].Value;
...
if CellValue<>'' then ...
...
ExcelApp.Workbooks.Close;
...
finally
ExcelApp.Quit;
coUninitialize;
end;
end.
Run Code Online (Sandbox Code Playgroud)
有时,当程序退出时,XLS保持锁定状态.查看任务管理器,我看到在客户端程序运行时启动的Excel.exe进程仍在运行,eventhoug客户端程序已退出并成功卸载.
你碰巧知道这种行为的常见嫌疑人是什么?知道在哪里寻找总是在客户端执行时卸载excel?
我有两个相同代码的变体:
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
IMyObject1 = interface
['{4411181F-3531-4D30-AB18-A8326F8C2CD0}']
end;
IMyObject2 = interface
['{41C88E1A-0360-4AC3-B021-125880B23DE5}']
end;
TMyObject = class(TInterfacedObject, IMyObject1, IMyObject2)
public
destructor Destroy; override;
end;
destructor TMyObject.Destroy;
begin
Writeln('Destroy');
inherited;
end;
procedure Variant1;
function GetMyObject: IMyObject2;
var
Obj1: IMyObject1;
begin
Obj1 := TMyObject.Create;
try
Obj1.QueryInterface(IMyObject2, Result);
finally
Obj1 := nil;
end;
end;
var
Obj2: IMyObject2;
begin
Obj2 := GetMyObject;
try
finally
Obj2 := nil;
end;
Writeln('Variant1 end of proc');
end;
function GetMyObject: IMyObject2;
var
Obj1: IMyObject1;
begin
Obj1 := …Run Code Online (Sandbox Code Playgroud)