Warum folgt auf jeden erfolgreichen Aufruf von QueryInterface () der Aufruf von Release ()?

8

Warum folgt auf einen QueryInterface() -Aufruf immer ein Release() -Aufruf? Zum Beispiel habe ich einen Beispielcode von MSDN wie folgt gesehen:

%Vor%

kann jemand die Absicht hinter Release() call hier erklären?

    
Arun Reddy Kandoor 18.02.2011, 23:36
quelle

3 Antworten

11

Es wird nicht immer direkt so gefolgt, obwohl das ziemlich üblich ist.

COM-Objekte werden als Referenz gezählt. Wenn Sie das Objekt anfänglich erstellen, erhalten Sie einen Zeiger auf ein IUnknown . Dann erhalten Sie eine andere Schnittstelle mit QueryInterface . Da dir das Interface IUnknown (normalerweise) egal ist, gibst du das frei. Wenn Sie die andere Schnittstelle freigeben, die Sie erhalten haben, wird die Referenzzahl 0 sein, damit das Objekt zerstört werden kann. Wenn Sie IUnknown nicht freigeben, bleibt der Referenzzähler jedoch nicht Null, so dass das Objekt nicht zerstört werden kann.

Der offensichtlichste Fall, in dem Sie nicht sofort die IUnknown freigeben, ist, wenn Sie mehr als eine andere Schnittstelle benötigen. In diesem Fall erhalten Sie IUnknown , dann die zweite und dritte Schnittstelle, bevor Sie IUnknown freigeben. Es gibt zumindest potentielle Fälle, in denen Sie die dritte (oder nachfolgende) Schnittstelle nicht sofort nach dem Erstellen des Objekts kennen könnten. Daher sollten Sie den Zugriff auf das IUnknown für einen beliebigen Zeitraum vor der Freigabe beibehalten.

    
Jerry Coffin 18.02.2011 23:43
quelle
6
  

Warum folgt auf einen QueryInterface-Aufruf immer ein Freigabeaufruf?

Weil QueryInterface AddRef , das den Verweis auf den Zeiger erhöht. Wenn es 0 Verweise auf einen Zeiger gibt, wird es für Sie freigegeben.

Hinweis: In den Antworten dieser Frage besteht eine gewisse Verwirrung darüber, was QueryInterface tatsächlich tut. Es ruft einfach Zeiger auf die unterstützten Schnittstellen eines Objekts ab und inkrementiert die Referenzzählung für dieses Objekt. Es erstellt kein neues Objekt für jede Schnittstelle, die es implementiert.

Wenn Sie zum Beispiel ein Objekt haben, das zwei Schnittstellen implementiert, würde der Aufruf dieses Objekt einfach als jede der Schnittstellen darstellen und eine Variable inkrementieren, die als Referenzzählung verwendet wird.

Hinweis: Die Referenzzählung kann auf verschiedene Arten implementiert werden, aber das obige erklärt das übliche Szenario. Insbesondere beschreibt @Ben eine Abreißschnittstelle, unter der die Wichtigkeit des Aufrufs von Release für den Interface-Pointer hervorgehoben wird, der an Sie zurückgegeben wurde.

    
Brian R. Bondy 18.02.2011 23:39
quelle
3

Dieses spezielle Code-Snippet scheint nur daran interessiert zu sein, den Wert ppv zu erhalten. Beachten Sie, dass nicht dieser Schnittstellenzeiger freigegeben ist. Die CDecoder-Klasse scheint das Fahrzeug zu sein, um es zu bekommen. Es gibt eine neue -Anweisung, um es zu erstellen, sonst nicht die COM-Standardmethode zum Erstellen einer COM-Klasse, die CoCreateInstance () verwendet. Offensichtlich erfordert die ordnungsgemäße Verwendung dieser Klasse einen Aufruf von Release () statt den Operator delete zu verwenden. Auch hier kein Standard, aber nicht unmöglich. Ich kann nur vermuten, dass CDecoder eine C ++ - Klasse ist, die eine COM-Co-Klasse implementiert und dieser Code verwendet sie direkt, anstatt die normalen COM-Prozeduren zu durchlaufen.

Gehen Sie nicht davon aus, dass dieser Code Standard ist. Es ist überhaupt nicht.

    
Hans Passant 19.02.2011 00:43
quelle