Why can the `as` operator raise an unpleasant EAccessViolation instead of the usual EIntfCastError?

I made a very experimental and unstable IDE add-on that causes extremely nasty A / V when the IDE completes (breaks the recent project function, grr!). I finally narrowed it down to a 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 occurs on read of address 0x00000008.

I added extra protection to the problem statement:

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

... and found out that (1) the pointer is still not nil(2) QueryInterfaceis still working (3) the desired interface is no longer present. Given that everything looks fine, I expect friendships EIntfCastError. But why do I have A / V instead?

+4
1

,

  • 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;
+4

Source: https://habr.com/ru/post/1537433/


All Articles