Domanda

I've made highly experimental and unstable IDE add-in, which causes extremely nasty A/V at IDE shutdown (breaks recent projects feature, grr!). I finally narrowed it down to the specific destructor:

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 exception happens on read of address 0x00000008.

I've added more defences to the problematic statement:

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

... and figured out what (1) pointer is still not nil (2) QueryInterface still works (3) desired interface no longer present. Given that everything looks normal, I expect friendly EIntfCastError. But why I've got A/V instead?

È stato utile?

Soluzione

My guess would be that either

  1. BorlandIDEServices itself is not nil but is also not valid anymore

  2. BorlandIDEServices is valid, but its internal IOTAMessageServices implementation is not.

Those could account for a read of address 0x00000008 error.

What you should do instead is obtain the IOTAMessageServices interface earlier in your add-in's lifetime and hold on to it, that way it is still valid in your destructor due to reference counting, eg:

{$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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top