我已经制作了高度实验性且不稳定的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;
read of address 0x00000008
上发生了A / V异常。
我在问题陈述中添加了更多防御措施:
if Assigned(BorlandIDEServices) then { passes }
if Supports(BorlandIDEServices, IOTAMessageServices) then { fails }
(BorlandIDEServices as IOTAMessageServices).AddTitleMessage('Goodbye');
...并弄清楚什么(1)指针仍然不是nil
(2)QueryInterface
仍然有效(3)所需的界面不再存在。鉴于一切看起来都很正常,我希望友好EIntfCastError
。但为什么我有A / V呢?
答案 0 :(得分:4)
我的猜测是
BorlandIDEServices
本身不是零,但也不再有效
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;