I have created a COM componenet named as Test.dll in that I have created an interface IDiscover.
Now i came to 2 ways of allocating the memory as
IDiscoverPtr id(__uuid(TestClass)); and Test::IDiscover *id=NULL;
What is the differnce between these two....Any Information is appreciated..
First one is a Smart Pointer and the Second one is a normal pointer.
You don't need to worry about Releasing a Smart Pointer whereas you have to explicitly Release() a normal COM Interface Pointer.
For more details on Smart Pointers, Look Here
Apart from that, the first one will try to find a GUID from registry for your Class named TestClass and will try to create an Instance of this class through CoCreateInstance API Call. It will try to get the IDiscover interface pointer through the said CoCreateInstance call and will throw an error if it fails to do so. On successful execution of the line IDiscoverPtr id(__uuid(TestClass));, you should have a valid IDiscover interface pointer in id.
The Second one is simply declaration of an Interface pointer, nothing else. You will have to instantiate it yourself through (most of the times) CoCreateInstance or one of it's variants.
The first variant is a smart pointer, the second one is a raw (ordinary pointer). The smart pointer will call IUnknown::Release() of the connected object when it itselft goes out of scope. The raw pointer will not do so and you will possibly get a memory leak unless you call IUnknown::Release() of the conected object explicitly at a suitable moment.
The first variant will try to instantiate the COM object upon its own construction (since you use the constructor parameterised with the class id) and throw an exception if that can't be done. See sources for _com_ptr_t (comip.h) for details. The second variant will give you a pointer initialized to null - not connected to any object.
Smart pointers for COM objects have a set of member function useful for instantiating objects and calling QueryInterface() - this can often reduce the amount of code needed to write. With a raw pointer you will have to call CoCreateInstance() with a handful of parameters most of which you will set to default values and this will force you to write more code. Again see the comip.h for the full sources of _com_ptr_t - they are quite readable.
The general recommendation is to use smart pointers unless you have real reasons to do otherwise.
Related
I found this code snippet here.
wil::com_ptr<IStream> stream;
CHECK_FAILURE(SHCreateStreamOnFileEx(
L"assets/EdgeWebView2-80.jpg", STGM_READ, FILE_ATTRIBUTE_NORMAL,
FALSE, nullptr, &stream));
According to the manual of SHCreateStreamOnFileEx, the type of the last argument is supposed to be IStream **. However the code snippet passes a wil::com_ptr<IStream> * to the function instead of a IStream **. I'm wondering how it works. Does wil::com_ptr<IStream> overload operator & (aka "address of")?
By the way, I cannot find the online manual of wil::com_ptr. Is it the same as winrt::com_ptr struct template (C++/WinRT)? Thanks.
The Windows Implementation Libraries (WIL) has its documentation published through its repository's wiki. The wil::com_ptr_t class template1 is described on the WinRT and COM wrappers page.
The section on Object management methods lists three class members that allow clients to get the address of the stored interface pointer:
T** addressof()
Returns the address of the internal pointer without releasing the current COM object. Do not use this for _Out_ parameters2 because it will leak the current COM object. For _Out_ parameters, use the & operator, which releases the current COM object before returning the address.
T** put()
Releases the current COM object and returns the address of the internal pointer. Use this method when passing the com_ptr_t as a _Out_ parameter.
T** operator&()
Same as put().
So to answer the literal question: Yes, wil::com_ptr_t does overload operator&() to return the address of the internal interface pointer after doing some housekeeping.
wil::com_ptr_t is unrelated to the winrt::com_ptr class template3, part of the C++/WinRT library. Neither of them are related to ATL's CComPtr or Visual Studio's _com_ptr_t. Those are the four official implementations, and while all of them have the same goal of automating lifetime management of COM objects they are subtly different in their implementations, with surprising consequences4.
The differences are in the following areas:
Constructors with an interface pointer argument
Implementations get to choose whether they assume ownership of the passed in interface pointer, or model shared ownership leaving the caller with the responsibility of Release()-ing the incoming interface pointer.
Assignment operators accepting an interface pointer
Same as above concerning the incoming pointer, with the added twist of having to handle the case where the instance is already holding an interface pointer. Implementations can:
Silently drop the currently held interface pointer (the fact that this is a bug doesn't mean that you won't see it)
Silently Release() the current interface prior to assigning the incoming interface pointer
Throw an exception in case the instance is holding an interface pointer
Retrieving the address of the raw interface pointer
Similar to the assignment above, the case where the smart pointer instance is already holding an interface needs to be handled, one way or another:
Silently drop the stored interface (e.g. addressof())
Silently Release() the current interface (e.g. put())
Throw an exception in case the stored pointer is not a nullptr
If you decide to use a COM smart pointer implementation, make sure you have a firm grasp on its semantics. The same literal piece of C++ code will potentially behave differently depending on the library in use.
1 wil::com_ptr is an alias template for wil::com_ptr_t with the err_policy template argument set to err_exception_policy.
2 The snippet in the question could have safely passed stream.addressof() even though ppstm is marked as an _Out_ parameter. I'm guessing that the author used operator&() instead for consistency, readability, and maintainability.
3 While the WIL and C++/WinRT are independent libraries they can interoperate with surprisingly little effort.
4 We're using a smart pointer, so we can't possibly be the source of the leak
I am writing code that utilizes COM interfaces. I am basing my code on examples that I have found online. I do not want to utilize smart pointers in this case because I want to understand the basics of COM and not just have a smart pointer class do all of the work for me.
In order to frame my questions, let's assume I have a class similar to the following:
public class TestClass
{
private:
IUnknown *m_pUnknown;
public:
TestClass();
void AssignValue();
}
TestClass::TestClass()
{
m_pUnknown = NULL;
}
void TestClass::AssignValue()
{
IUnknown *pUnknown = NULL;
//Assign value to pUnknown here - not relevant to my questions
m_pUnknown = pUnknown;
pUnknown->Release();
}
Now on to my specific questions.
1) The examples I've seen to not use AddRef() when initializing a value, such as in the class constructor. Does the AddRef() happen "automatically" behind the scenes when a COM pointer is first assigned a value?
2) Although my code example does not show it, it is my understanding that in the AssignValue() method, when you assign a second value to overwrite the value of pUnknown (originally set in the class constructor), Release() is automatically called. After assigning the new value to pUnknown its reference count stands at zero. I need to call pUnknown->AddRef() immediately after the reassignment. Is my understanding correct?
Notes: I assume we are ignoring exceptions for simplicity here. If this was for real, you would want to use smart pointers to help keep things straight in the presence of exceptions. Similarly, I am not worrying about proper copying or destruction of instances of your example class or multi-threading. (Your raw pointers cannot be used from different threads as simply as you might assume.)
First, You need to make any necessary calls to COM. The only way anything might happen "automatically" behind the scenes would be if you were using smart pointers to do them.
1) The examples you refer to have to be getting their COM interface pointers from somewhere. This would be by making COM calls, e.g., CoCreateInstance() and QueryInterface(). These calls are passed the address of your raw pointer and set that raw pointer to the appropriate value. If they weren't also implicitly AddRef'ed, the reference count might be 0 and COM could delete the associated COM object before your program could do anything about it. So such COM calls must include an implicit AddRef() on your behalf. You are responsible for a Release() to match this implicit AddRef() that you instigated with one of these other calls.
2a) Raw pointers are raw pointers. Their value is garbage until you arrange for them to be set to something valid. In particular, assigning a value to one will NOT auto-magically call a function. Assigning to a raw pointer to an interface does not call Release() - you need to do that at the appropriate time. In your post, it appears that you are "overwriting" a raw pointer that had previously been set to NULL, hence there was no existing COM interface instance in the picture. There could not have been an AddRef() on something that doesn't exist, and must not be a Release() on something that isn't there.
2b)
Some of the code you indicated by a comment in your example is very relevant, but can easily be inferred. You have a local raw pointer variable, pUnknown. In the absent code, you presumably use a COM call that obtains an interface pointer, implicitly AddRefs it, and fills in your raw pointer with the proper value to use it. This gives you the responsibility for one corresponding Release() when you are done with it.
Next, you set a member raw pointer variable (m_pUnknown) with this same value. Depending on the previous use of this member variable, you might have needed to call Release() with its former value before doing this.
You now have 2 raw pointers set to the value to work with this COM interface instance and responsibility for one Release() due to 1 implicit AddRef() call. There are two ways to deal with this, but neither is quite what you have in your sample.
The first, most straightforward, and proper approach (which others have correctly pointed out & I skipped passed in the first version of this answer) is one AddRef() and one Release() per pointer. Your code is missing this for m_pUnknown. This requires adding m_pUnknown->AddRef() immediately after the assignment to m_pUnknown and 1 corresponding call to Release() "someplace else" when you are done using the current interface pointer from m_pUnknown. One usual candidate for this "someplace else" in your code is in the class destructor.
The second approach is more efficient, but less obvious. Even if you decide not to use it, you may see it, so should at least be aware of it. Following the first approach you would have the code sequence:
m_pUnknown = pUnknown;
m_pUnknown->AddRef();
pUnknown->Release();
Since pUnknown and m_pUnknown are set the same here, the Release() is immediately undoing the AddRef(). In this circumstance, eliding this AddRef/Release pair is reference count neutral and saves 2 round trips into COM. My mental model for this is a transfer of the interface and reference count from one pointer to the other. (With smart pointers it would look like newPtr.Attach( oldPtr.Detach() ); ) This approach leaves you with the original/not shown implicit AddRef() and needing to add the same m_pUnknown->Release() "someplace else" as in the first alternative.
In either approach, you exactly match AddRefs (implicit or explicit) with Releases for each interface and never go to a 0 reference count until you are done with the interface. Once you do hit 0, you do not attempt to use the value in the pointer.
Avi Berger already posted a great answer, but here is the same thing stated another way in case it helps with understanding.
In COM, reference counting is done within the COM object. The COM runtime will destruct and free an object whose reference count reaches 0. (This might be delayed by some time from the point of the count hitting 0).
Everything else is a convention. The usual convention amongst C++ COM programmers is that raw interface pointers should be treated as owning pointers. This concept means that any time a pointer points to a COM object, the pointer owns that object.
Using this terminology, the object may have multiple owners at any one time, and the object will be destroyed when nobody owns it.
However, raw pointers in C++ don't have ownership semantics built in. So you have to implement it yourself by making function calls:
Call AddRef on an interface pointer when that pointer takes ownership of an object. (You'll need to be aware of which Windows API functions or other library functions already do this, to avoid you doing it twice)
Call Release on an interface pointer when that pointer is about to stop owning an object.
The benefit of smart pointers is that they make it impossible for you to forget to call Release when an interface pointer stops owning an object. This includes the following cases:
Pointer goes out of scope.
Pointer is made to stop pointing to the object, by using assignment operator.
So, looking at your sample code. You have the pointer m_pUnknown. You want this pointer to take ownership of the object, so the code should be:
m_pUnknown = pUnknown;
m_pUnknown->AddRef();
You will also need to add code to your class destructor and your class assignment operator to call m_pUnknown->Release(). I would very strongly recommend wrapping these calls in the smallest class possible (that is, write your own smart pointer and make TestClass have that smart pointer as a member variable). Assuming of course you don't want to use an existing COM smart pointer class for pedagogical reasons.
The call pUnknown->Release(); is correct because pUnknown currently owns the object, and the pointer is about to stop owning the object due to the fact that it will be destroyed when the function block ends.
You may observe that it would be possible to remove both of the lines m_pUnknown->AddRef() and pUnknown->Release(). The code will behave exactly the same. However , it is better to follow the convention outlined above. Sticking to a convention helps yourself to avoid errors and it also helps other coders to understand your code.
To put it another way, the usual convention is to think of the pointer as having a reference count of either 0 or 1, even though the reference counting is not actually implemented that way.
First, my apologies. My attempt to simplify my code for the sake of clarity turned out to be misguided. However, I believe my questions were answered. If I may, I will summarize.
1) Any COM object that is assigned a value other than NULL needs to be immediately followed by AddRef() unless the AddRef() was implicitly handled (as is the case with some Windows API calls).
2) Any reassignment of value to a COM pointer, assuming that the "before" value is not NULL must be immediately proceeded by Release(). AddRef() would then by needed as mentioned in #1.
3) Any COM variable whose value needs to be preserved beyond its current scope requires that it have a reference count of at least 1 upon exiting its said scope. This may mean that an AddRef() is required.
Would this be a fair summary? Did I miss anything?
Suppose I have an API-border function that creates and returns an object:
<?> createOneObject();
What would be the best way to return the object to the caller?
Return the raw MyObject* and let the caller handle the pointer herself
Return std::shared_ptr<MyObject>
Something else?
Depends.
In general, returning a raw pointer is bad, because the type itself does not communicate ownership. Should the user delete the pointer? If yes, then how? If not, then when does the library do it? How does the user know if the pointer is still valid? Those things have to be documented, and lazy programmers might skip reading the docs. But, if your API must be callable from C or other languages, then a raw pointer may be the only option.
Shared pointer might be useful in special cases, but they do have overhead. If you don't need shared ownership, then use of a shared pointer may be overkill.
Unique pointer is what I would use unless there is specific reason to use something else.
Although, that assumes that a pointer should be returned in the first place. Another great option could be to return an object.
To be a bit more concrete: I have a player class that just stores an id and just offers lots of methods. In this case you would prefer to return by value?
Most definitely.
You have 2 options (without any nasty drawbacks):
C Style
Have a matching void destroyOneObject(MyObject* object); that cleans up the resource. This is the proper choice when destroying the object isn't as simple as deleting it (e.g. needs to be unregistered at some manager class).
Smart pointer
When all that needs to happen is to delete the object, return a std::unique_ptr<MyObject>. This uses RAII to clean up the object, and fits modern C++ a lot better.
The bad solutions
Don't return a raw pointer and call delete on it. You cannot guarantee that the delete matches the new that was used to create the object. It also doesn't communicate very well if you are supposed to delete it in the first place.
Don't use shared pointers. They are complete overkill in almost any situation, and are usually the result of a lack of understanding of an application's structure.
I was wondering if it is standard practice in COM libraries to call Addref on an COM interface, that is returned from a function. For instance:
IXMLDOMElement* domElement = NULL;
document_->get_documentElement(&domElement); // does get_documentElement() call Addref on domElement?
// ...
// do something with domElement
// ..
domElement.Release(); // correct?
// (btw. member variable document_ is of type CComPtr<IXMLDOMDocument2>
or with a smart pointer:
CComPtr<IXMLDOMElement> domElement;
document_->get_documentElement(&domElement);
Btw. I found that in the docs of MSXML for "Windows media 9 series" it says that Addref is called: http://msdn.microsoft.com/en-us/library/ms751196(v=vs.85).aspx
But in the official documentation nothing is mentioned about it:
http://msdn.microsoft.com/en-us/library/ms759095(v=vs.85).aspx
The function that returns an interface pointer must call AddRef() on it before exiting, not the function that is receiving the object. The function that receives the interface pointer must use it as-is and then call Release() on it. Which means that get_documentElement() will call AddRef(), so do not call it yourself.
The rules for who - the caller or the callee - is responsible for doing what in regards to reference counting and memory management in COM are clearly defined in COM's documentation on MSDN:
The Rules of the Component Object Model
Reference Counting Rules
Yes you are supposed to addref before returning a COM object, as the caller is going to have an new interface pointer referencing the object, so the reference count needs to be increased by one. This is the rule, not the exception.
Documenting the internal addref is the exception, however, as reference counting is one of the fundamentals of COM. Probably the documentation was written when a lot of callers of this method don't know the rule and caused too many memory leaks.
When you, as a caller, no longer need the received object, you need to call Release directly or indirectly (e.g. through a class destructor), and stop using the reference pointer (many people set the pointer to null to prevent dangling pointers).
I have a pointer to a QScriptEngine that I'm passing through the overloaded class constructor of class Evaluator and assigns it to QScriptEngine *engine_ (class Property subclasses Evaluator, and calls this constructor of Evaluator, passing it an already allocated QScriptEngine). The constructor with no arguments creates the new QScriptEngine pointer (class Generic subclasses Evaluator in this way). In the destructor I test if engine_ is not NULL, delete the pointer, then assign it NULL. Should the pointer (engine_) in the derived Property now also be NULL? Something tells me this is not the case. If not, how do you deal with this situation? I need the QScriptEngine to be the same instance throughout. QScriptEngine's = operator is private, or I would be avoiding the pointer all together.
I saw some info on shared pointers (boost::shared_ptr and std:tr1::shared_ptr) in another SO question. I'm already using boost for the regex library, so boost is not out of the question if that's the best way to deal with this. Hopefully there's a non-boost way, for general C++ knowledge and future projects.
You can solve this by giving one of the classes (class A) lifetime control of that pointer, along with a 'getter' method. The other class (class B) would always call A's getter whenever it needed the pointer. That way, A remains in control of the pointer at all times. Downside is the getter function (it will probably inline, but it's still a second indirection). Also, B is going to have to check that pointer for NULL on pretty much every use.
Your other choice is to wrap the pointer in something like boost::shared_ptr which takes care of the problem (if used properly) by holding the underlying pointer, and only deleting it when all objects that share that pointer are deleted. You could write this yourself, but since you already have boost in play, I'd just use their implementation.
A third choice is to re-factor the whole thing so that you don't need a shared pointer. I'd personally never design a C++ program that needed shared pointers, just because it's a spot where memory management bugs could easily creep in over the years, but that's just me.