相关疑难解决方法(0)

意外的隐式接口变量的神秘案例

我最近遇到了一些我无法解释的行为,与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)

delphi interface

8
推荐指数
2
解决办法
1467
查看次数

是实现Delphi接口引用计数的未来证明

我有一个助手类,将在整个应用程序中广泛使用.实现依赖于接口引用计数,这个想法大致是:

...
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 implementation interface reference-counting

8
推荐指数
1
解决办法
562
查看次数

运行delphi客户端自动化程序后excel.exe保持加载的原因?

我编写了一个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?

delphi excel office-automation

8
推荐指数
1
解决办法
5408
查看次数

最后一次IUnknown.Release调用的时刻

我有两个相同代码的变体:

{$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)

delphi

8
推荐指数
1
解决办法
158
查看次数