Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does IUnknown::QueryInterface() increment the reference count?

If I have an IUnknown *ptr, do I need to call Release() on every interface I obtain through ptr->QueryInterface(), in addition to calling ptr->Release() when I'm done with ptr?

I used to think that the answer is "Yes", but this quote from MSDN confused me:

Occasionally you may need to obtain a weak reference to an object (that is, you may wish to obtain a pointer to one of its interfaces without incrementing the reference count), but it is not acceptable to do this by calling QueryInterface followed by Release.

I don't understand why that's problematic -- if I call ptr->QueryInterface() and then call Release on the resulting pointer, shouldn't the reference count on the object still be positive? How does that result in an invalid pointer?

like image 342
user541686 Avatar asked Sep 11 '11 04:09

user541686


People also ask

What does QueryInterface do?

Used to retrieve an interface pointer, supplying the IID value of the requested interface automatically based on the type of the interface pointer used.

How do you find the reference count of a COM object?

You can do this by putting break points or using print(CFGetRetainCount(CFTypeRef!)) function in your code . You can also increment the reference count of an Object using the CFRetain function, and decrement the reference count using the CFRelease function. CFRetain(CFTypeRef cf);CFRelease(CFTypeRef cf);

What is AddRef?

AddRef is used to increment the reference count when a new client is acquiring the object. It returns the new reference count. Release is used to decrement the reference count when clients have finished using the object. It returns the new reference count.


1 Answers

The documentation is correct. And you need to follow reference counting rules - that includes calling Release on interfaces obtained from QueryInterface in addition to after you created the object.

To clear up why you can't do weak pointers with Release - there exists a race condition in calling QueryInterface and then Release immediately after.

  • Thread1 creates object - reference count 1
  • Thread2 calls QueryInterface for weak reference - reference count 2
  • Thread1 releases object - reference count 1
  • Thread2 calls Release for weak reference - reference count 0. Object is destroyed.
  • Thread2 tries to use object - error.

The warning is there to guard against the above - presumably some programmers think that they can "call ptr->QueryInterface() and then call Release on the resulting pointer" and then use the object...

like image 152
ta.speot.is Avatar answered Oct 09 '22 11:10

ta.speot.is