Why `as` operator might throw nasty EAccessViolation instead of normal EIntfCastError?
debugging, delphi, ide, toolsapi
Solution
My guess would be that either
`BorlandIDEServices` itself is not nil but is also not valid anymore
`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;
Problem
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?