4

我制作了高度实验性且不稳定的 IDE 插件,这会在 IDE 关闭时导致非常讨厌的 A/V(破坏了最近的项目功能,grr!)。我最终将其缩小到特定的析构函数:

destructor TMyAddIn.Destroy;
begin
  {$IFDEF DEBUG}
  { BUG is here, causes A/V at shutdown }
  (BorlandIDEServices as IOTAMessageServices).AddTitleMessage('Goodbye');
  {$ENDIF}

  { ... }
  { finalizing stuff }
  { ... }

   inherited;
end;

A/V 异常发生在read of address 0x00000008.

我为有问题的陈述添加了更多防御措施:

  if Assigned(BorlandIDEServices) then    { passes }
    if Supports(BorlandIDEServices, IOTAMessageServices) then   { fails }
     (BorlandIDEServices as IOTAMessageServices).AddTitleMessage('Goodbye');

...并弄清楚(1)指针仍然没有nil(2)QueryInterface仍然有效(3)所需的接口不再存在。鉴于一切看起来都很正常,我希望友好EIntfCastError。但是为什么我有 A/V 呢?

4

1 回答 1

4

我的猜测是

  1. BorlandIDEServices本身不是 nil 但也不再有效

  2. BorlandIDEServices是有效的,但它的内部IOTAMessageServices实现不是。

这些可能会导致read of address 0x00000008错误。

相反,您应该做的是IOTAMessageServices在加载项生命周期的早期获取接口并保留它,这样由于引用计数,它在您的析构函数中仍然有效,例如:

{$IFDEF DEBUG}
private
  MsgSvc: IOTAMessageServices;
{$ENDIF}

constructor TMyAddIn.Create;
begin
  inherited;

  { ... }
  { initializing stuff }
  { ... }

  {$IFDEF DEBUG}
  MsgSvc := BorlandIDEServices as IOTAMessageServices;
  MsgSvc.AddTitleMessage('Hello');
  {$ENDIF}
end;

destructor TMyAddIn.Destroy;
begin
  {$IFDEF DEBUG}
  MsgSvc.AddTitleMessage('Goodbye');
  {$ENDIF}

  { ... }
  { finalizing stuff }
  { ... }

   inherited;
end;
于 2014-04-22T01:52:51.973 回答