Ich bin kürzlich auf ein Verhalten gestoßen, das ich einfach nicht erklären konnte und kann, in Bezug auf Delphi-Interface-Variablen.
Im Wesentlichen läuft es auf eine implizite Schnittstellenvariable hinaus, die der Compiler in der Methode Broadcast
generiert.
Bei der Endanweisung, die die Methode beendet, enthält der Epilogcode zwei Aufrufe von IntfClear
. Eines davon kann ich erklären, es entspricht der lokalen Variable Listener
. Die andere kann ich nicht erklären und es bringt Sie zu TComponent._Release
(Debug DCUs) nachdem die Objektinstanz zerstört wurde. Es führt nicht zu einem AV, aber das ist nur ein Glück, und mit Full FastMM debug wird ein Post-Destruction-Instanzzugriff gemeldet.
Hier ist der Code:
%Vor%Und hier ist die Demontage des Epilogs:
Dort, klar wie der Tag, sind die beiden Aufrufe von IntfClear.
Wer kann also die offensichtliche Erklärung sehen, dass ich vermisse?
AKTUALISIEREN
Nun, Uwe hat es sofort verstanden. FListeners[i]
benötigt eine temporäre implizite Variable für die Ergebnisvariable. Ich habe das nicht gesehen, seit ich Listener
zugewiesen habe, aber natürlich ist das eine andere Variable.
Die folgende Variante ist eine explizite Darstellung dessen, was der Compiler für meinen ursprünglichen Code generiert.
%Vor%Wenn so geschrieben wird, ist es offensichtlich, dass Intf erst im Epilog gelöscht werden kann.
Uwe Raabe hat Recht, wenn Sie sich den Code weiter oben ansehen:
%Vor% Sie können sehen, wie das Ergebnis des Aufrufs FListeners [i] in [ebp- $ 20] platziert wird und dann procedure _IntfCast(var Dest: IInterface; const Source: IInterface; const IID: TGUID);
aufgerufen wird (eax ist das Ziel, [ebp- $ 10], edx die Quelle, [ ebp- $ 20], und ecx die Adresse, an der die passende GUID gefunden werden kann.
Sie können Ihren Code reparieren, indem Sie die Broadcast-Methode in
ändern %Vor%