I recently came across some behaviour that I simply could not and cannot explain, related to Delphi interface variables.
Essentially, it boils down to an implicit in
Uwe Raabe is correct, if you look at the code further up:
Project4.dpr.51: Listener := FListeners[i] as IListener;
00441C16 8D4DE0 lea ecx,[ebp-$20]
00441C19 8B55F4 mov edx,[ebp-$0c]
00441C1C 8B45FC mov eax,[ebp-$04]
00441C1F 8B4004 mov eax,[eax+$04]
00441C22 8B18 mov ebx,[eax]
00441C24 FF530C call dword ptr [ebx+$0c]
00441C27 8B55E0 mov edx,[ebp-$20]
00441C2A 8D45F0 lea eax,[ebp-$10]
00441C2D B9A81C4400 mov ecx,$00441ca8
00441C32 E8A573FCFF call @IntfCast
You can see how the result of the FListeners[i] call is placed in [ebp-$20] and then procedure _IntfCast(var Dest: IInterface; const Source: IInterface; const IID: TGUID);
is called on that (eax being the target, [ebp-$10], edx the source, [ebp-$20], and ecx the address where the appropriate guid can be found.
You can fix your code by changing the Broadcast method to:
procedure TBroadcaster.Broadcast(Msg: Integer);
var
i: Integer;
Intf: IInterface;
Listener: IListener;
begin
for i := 0 to FListeners.Count-1 do begin
Intf := FListeners[i];
if Supports(Intf, IListener, Listener) then
Listener.HandleMessage(Msg);
end;
Listener := nil;
Intf := nil;
FListeners.Clear;
FreeAndNil(FListener);
end;//method epilogue: why is there a call to IntfClear and then TComponent._Release?
Just a guess, but perhaps the FListeners[i] as IListener
uses a temporary variable for FListeners[i]
. After all it is the result of a function call.