I think..
Attach and Detach makes no change in the reference count.
But Destructor of CComPtr call release on the pointer it contains.
So is it necessary to call detach every time when one use attach?...
{
CComPtr<IObj> pPtr;
pPtr.Attach(pPtr1);
.....//No detach on pPtr
}
As you mentioned, Attach/Detach don't affect reference counter, by design. So you are to use them when you have a special need to skip adding a reference. Otherwise you initialize the pointer in a more natural way (constructor, assignment operator etc).
Your special need for Attach is typically to compensate external reference already added. So that your CComPtr destructor would correctly release it when it is time to.
So, no, you don't have to pair Attach with Detach. When you have to, you supposedly would not use Attach in first place.
For example, Attach:
{
// We have an oustanding reference on pRawFoo we want to safely compensate for
CComPtr pFoo;
pFoo.Attach(pRawFoo); // No effect on counter, but since here we would release
// the reference going out of scope
// ...
} // ~CComPtr releases the reference as intended
No need in Attach:
{
// External pRawFoo is in proper balance in terms of reference count
CComPtr pFoo;
pFoo = pRawFoo; // No need in Attach, pFoo adds a reference
// ...
} // ~CComPtr releases the reference as intended
Like most smart pointers, CComPtr<T> indicates ownership and uses RAII semantics to ensure that an owned resource is properly cleaned up. The methods Attach and Detach are used to transfer ownership, in part because the reference count bookkeeping can be relatively expensive. So the question you need to answer in your context is what the pattern of ownership is.
When transferring ownership between two CComPtr<T> objects, there will be a tendency to match Attach and Detach calls, but they will be on the separate objects:
spFoo2.Attach(spFoo1.Detach());
Consider the following snippets and what they indicate about ownership of the IFoo object. Both m_spFoo and spFoo are intended to be CComPtr<IFoo> values:
HRESULT C::GetFoo_1(IFoo **ppFoo)
{
return m_spFoo.QueryInterface(ppFoo); // or m_spFoo.CopyTo(ppFoo)
}
HRESULT C::GetFoo_2(IFoo **ppFoo)
{
*ppFoo = m_spFoo.Detach();
return S_OK;
}
spFoo = obj.GetFoo_3();
spFoo.Attach(obj.GetFoo_4());
Here's my take on these snippets.
The first is a very usual way to return an IFoo to a caller, following the usual semantics wherein the caller receives a copy with an incremented reference count.
The second is okay if ownership is being passed to the caller; the caller takes the copy that the C object previously had.
The third is probably returning a CComPtr<IFoo> or CComPtr<IFoo>& already (the non-reference case can lead to extra reference count bookkeeping) and we are indicating further shared ownership; that is, we want to keep it around for longer than that statement.
The fourth indicates unusual semantics in GetFoo_4, as it must have provided a reference count on a raw IFoo* that we don't want to further increment.
Related
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?
If I create the pointer of any COM interface and then assign it to an object of CComPtr of same COM Interface do I need to release the original COM pointer?
ISomeComInterface* pSomeComInterface = new CSomeComInterfaceImplemented();
CComPtr<ISomeComInterface> cptrSomeComInterface = pSomeComInterface;
// ....
// Do I need to Release original COM Pointer.
pSomeComInterface->Release();
Yes, you may need release the previous pointer;
CComPtr::operator =
This operation AddRefs the new object and releases the existing object, if one exists.
From MSDN. CComPtr is used to manage the lifetime of the COM object (it applies the RAII idiom to COM objects) - it manages the reference count itself.
However, the technique you are using to create the COM object is unusual and it seems to not perform the AddRef(); hence in this case the Release() would not be needed.
The common manner to create a COM object with CComPtr is to use the CoCreateInstance method of CComPtr. In which case the AddRef() and Release() methods are managed by the CComPtr and should not be called by your client code.
CComPtr takes care of reference count of its internal interface pointer, managed by the instance of the class. It has no effect on reference counts of other pointers. That is, having assigned the pointer to the variable, you can be sure that CComPtr's internal pointer is AddRef'ded and Release'd as necessary, however you should take care of your raw interface pointer variable pSomeComInterface yourself and make explicit Release call.
This depends on how the COM object constructor initializes the reference count. Most likely it sets it to zero so you don't need an extra Release() call. CComPtr will then take care of the object.
Look into how the COM object initializes the reference count to be sure. It's not illegal to set the reference count to anything other than zero, the only requirement is that once the object pointer is returned to COM client the reference count is set to one and ownership is so passed to the client. Strictly speaking because you new the object instead of calling CoCreateInstance() or calling a method of a COM object you're not guaranteed any specific value.
So the following could be legal if reference count is set to one in object constructor:
HRESULT ComMethod( Type** result )
{
if( result == 0 ) {
return E_POINTER;
}
//refcount set to 1 in constructor,
//so no AddRef() call
*result = new Type();
return S_OK;
}
I have been working with d3d11 for quite a while now, and after discovering the directx debugger, i've recently discovered that my program is leaking memory everywhere from all the com objects that aren't releasing properly. After a bit of snooping around and hours of staring at the code, i've developed some methods to isolate where i'm getting these unexpected increases to the ref counts.
first off, all of the objects are wrapped in std::shared_ptrs with custom deleters that call their respective release function. I did this so i would never have to call addref, and the first call to release, the one in the deleter, would only be called when the object went out of scope. It would look something like this:
// in D3D11Renderer.h
...
// declaration
std::shared_ptr<ID3D11Device *> m_Device;
...
// after call to ID3D11CreateDeviceAndSwapChain
m_Device.reset(device, [](ID3D11Device * ptr){ptr->Release();})
Problem is certain random functions in the api calls will just randomly increase the ref count, expecting me to have to deal with it later.
something i found useful in diagnosis was a function that looked like this:
template <typename T>
int getRefCount(T object)
{
object->AddRef();
return object->Release();
}
which, just increments and decrements that count to obtain the current count of refs on that object. Using this, i found that, just before the release in the custom deleter is called, there are 10 outstanding references to the 1 ID3D11Device i created. Curious, i backtracked slowly, calling this function all the way back through the program, right up to where i originally created it. Funny thing, just after i first create the object, (even before the shared_ptr takes ownership), the number of outstanding refs is already 3! This occurs immediately after this here.
result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1,
D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, NULL, &deviceContext);
if(FAILED(result))
{
return false;
}
this is the first time i call any such function that creates the device, and when i check to see how many refs there are right after, and it says 3! So clearly, I'm misunderstanding something about the way these com objects are supposed to be handled. Is there any such way that i can just manually delete them, rather then use there behind-the-scenes ref counting nonsense?
Every time you create a buffer or a shader or anything that depends on the device, that object will likely contain a reference to the device so will bump up it's reference count to ensure it's not deleted while it is still using it.
It sounds like your approach might well work overall, as you'll essentially keep one single reference to the device in your code to stop it being deleted, and when all your internal references are gone release it. However d3d will still be doing it's own reference counting and so the reference count will only drop to zero when you release every reference to every other related object. Even just creating the swap chain and device will make back buffers and so on that likely need to maintain a reference to the device.
I tried this same idea for a while... And in the end found it much easier to just
#include <atlbase>
Then use
CComPtr<ID311Device> m_Device
as that's pretty much exactly what that class is designed for and it's more lightweight than std::shader_ptr as the objects already have a reference counter in them so there is no need to keep a separate one.
Using shared_ptr is not correct for Direct3D (COM) objects, even if you use custom deleters.
First, COM objects use intrusive reference counting, which means the reference count is stored in the object itself. shared_ptr on the other hand uses non-intrusive reference counting, which means the reference count is stored in the smart poiter object. Therefore, using shared_ptr for COM objects means that you have two separate, independent reference counts: the COM object's, and the shared_ptr's.
Second, using a custom deleter solves the problem of properly releasing the object, but it doesn't solve the problem of properly acquiring a reference to the object. Assigning a COM object to a shared_ptr will increment the reference count of the shared_ptr, but not the object's.
That explains why you're leaking objects: D3D methods increment objects' reference counts, but you are using shared_ptrs that decrement the object's reference count only once for the entire lifetime of the object (when all shared_ptrs pointing to the object are destroyed).
So, you need to use a COM smart pointer, such as ATL's CComPtr.
I have a reference to an object and want to call a function that takes a boost::shared_ptr of this object. If I build a boost::shared_ptr to make the call when my boost::shared_ptr is canceled from the stack than the object is canceled too! This is exactly what happens when I run this code:
double f(boost::shared_ptr<Obj>& object)
{
...
}
double g(Obj& object)
{
boost::shared_ptr<Obj> p(&object);
double x = f(p);
...
}
Is there a way to make it work? How can I create in g() a boost::shared pointer that leaves my object alive at the end? I think I have to connect it to the reference counting machinery of other shared pointers that already point to object... but how?
Even if I make it work do you think this way of doing is bad design? What is the best practice to solve this kind of problems? In my code I have objects and methods that work both with shared pointer and references and I cannot work only with these or those...
A function that takes a shared_ptr is saying something about what it does. It is saying, "I want to potentially claim shared ownership of this object". If this is not true, then it is a poorly written function and shouldn't be taking a shared_ptr at all.
A function which takes a value by non-const reference to an object means that the function can modify the object, but cannot claim ownership. If you don't own something, you also can't give ownership to someone else.
Now, you could perform this trick of using an empty deleter function:
void EmptyDeleter(Obj *) {}
double g(Obj& object)
{
boost::shared_ptr<Obj> p(&object, EmptyDeleter);
double x = f(p);
...
}
However, you are now lying to f. It doesn't own object; it can't own object. It is very possible that object is a stack object that may disappear any time after f completes. If f were a member of a class, it might store the shared_ptr in a member variable. At which point, it would then have a shared_ptr to a dead object. This is exactly the sort of thing that shared_ptrs are intended to prevent.
The correct answer is for either f to not take its argument by shared_ptr (use non-const reference or non-const pointer if it is modifiable, and const& if it is not modifiable), or for g to take its argument by shared_ptr.
You may create a shared_ptr that doesn't actually free the object. Like this:
struct FictiveDisposer {
template <class T> void operator ()(T) {}
};
Obj& object = /* ... */;
boost::shared_ptr<Obj> myPtr(&obj, FictiveDisposer ());
// you may use myPtr
However you should use this carefully. If you're sure the function you're calling won't try to "save" your object for later use - there's no problem. Otherwise you must guarantee that the lifetime of the saved shared_ptr to your object won't exceed the actual lifetime of your object.
In simple words: you got the reference to the object. You didn't create it, and you may not affect its lifetime (neither shared_ptr can). Hence there may happen a situation where the object doesn't exist anymore, still it's referenced by shared_ptr. This must be avoided.
You must consider the purpose of f(). Presumably if it takes a shared_ptr, f intends to retain shared ownership of this pointer over time, past its return. Why? What is f() assuming when you pass it a shared_ptr? Once you answer this question you will be able to figure out how to code g().
If for some reason f() does not need to retain shared ownership of the pointer, then if you have control over its interface it could be rewritten to take a Obj* or Obj& instead of a shared_ptr. Any code possessing a shared_ptr could then call f by pulling the pointer out of the shared_ptr or dereferencing it.
It's usually a sign of poor design for a library interface to take a
shared_ptr (but there are exceptions). Since the function you're
calling expects to take responsibility, or at least partial
responsibility, for the object you pass it, and the rest of the code
isn't prepared for this, you're only safe solution is to clone the
object, e.g.:
double x = f( boost::shared_ptr<Obj>( new Obj( object ) ) );
But you'd really be best off finding out why f requires a
shared_ptr, and why g can't take one as an argument.
How can I create in g() a boost::shared pointer that leaves my object alive at the end?
You can give the shared pointer a custom destructor that does nothing:
boost::shared_ptr<Obj> p(&object, [](void*){});
or if your compiler doesn't support lambdas:
void do_nothing(void*) {}
boost::shared_ptr<Obj> p(&object, do_nothing);
Even if I make it work do you think this way of doing is bad design?
Yes: you lose the lifetime management that shared pointers give you, and it is now your responsibility to make sure that the object outlives all of the shared pointers.
What is the best practice to solve this kind of problems?
Decide on an ownership model for all the objects you're using, and stick to it. Shared pointers can be useful when you want to share ownership, but not otherwise. In your case f wants to share ownership, and whatever calls g seems to want exclusive ownership; it would be a good idea to think about why they want that, and whether you can change one to be compatible with the other.
std::shared_ptr<T> is to possible give multiple entities ownership of the referenced object. If an interface expects a std::shared_ptr<T> there are two possibilities:
Someone ignorantly used std::shared_ptr<T> in an interface which was meant to receive a T object or a reference or a pointer to a T object. If that is the case the author shall be educated (and if this doesn't work be released from his current duties to pursue a new career) and the interface corrected.
Since now all interfaces using a std::shared_ptr<T> are using this to possibly grant shared ownership to the object, it should be obvious that a stack allocated T isn't a suitable argument to such an interface. The only possible argument is a T object whose life-time is maintained vy a std::shared_ptr<T>.
I realize that this doesn't answer the original question but it should be clear that the only viable course of action is: don't ever try to pass an object to a function taking a std::shared_ptr<T> which can't be fully controlled by such a pointer! (the same applies to the boost version of shared pointers).
Consider the following example code which I have recently seen in our code base:
void ClassA::ExportAnimation(auto_ptr<CAnimation> animation)
{
... does something
}
// calling method:
void classB::someMethod()
{
auto_ptr<CAnimation> animation (new CAnimation(1,2));
ClassA classAInstance;
classAInstance.ExportAnimation(animation)
... do some more stuff
}
I don't like this - and would rather write it so:
void ClassA::ExportAnimation(CAnimation* animation)
{
... does something
}
// calling method:
void classB::someMethod()
{
auto_ptr<CAnimation> animation (new CAnimation(1,2));
ClassA classAInstance;
classAInstance.ExportAnimation(animation.get())
... do some more stuff
}
but it is really a problem?
It all depends on what ExportAnimation is and how it is implemented.
Does it only use the object for the duration of the call and then leaves it?
Then convert to a reference and pass a real reference. There is no need to pass membership and the argument is not optional, so void ExportAnimation( CAnimation const & ) suffices. The advantage is that it is clear from the interface that there is no memory management issues with the method, it will just use the passed object and leave it as such. In this case, passing a raw pointer (as in your proposed code) is much worse than passing a reference in that it is not clear whether ExportAnimation is or not responsible for deletion of the passed in object.
Does it keep the object for later use?
This could be the case if the function starts a thread to export the animation in the background. In this case, it has to be clear that the lifetime of the argument must extend beyond the duration of the call. This can be solved by using shared_ptr --both in the function and outside of it-- as they convey the object is shared and will be kept alive as much as required meaning. Or else you can actually transfer ownership.
In the later case, if transfer of ownership is performed, then the initial code is fine --the signature is explicit in the ownership transfer. Else you can opt to document the behavior, change to a raw pointer and make the transfer explicit by calling ExportAnimation( myAnimation.release() ).
You have added some concerns as a comment to another answer:
can I really see that object no longer exists after the method call?
The caller auto_ptr is reset to 0 in the call, so any dereference will kill be an error and will be flagged in the first test you try.
I would need to look at the header file to see that the parameter type is an auto_ptr and not a normal pointer.
You do not need to look at the header... just try passing a raw pointer and the compiler will tell you that it requires an auto_ptr<> --There is no implicit conversion from raw pointer to auto_ptr.
I would expect the object to exist until the auto_ptr goes out of scope.
The standard auto_ptr, unlike boost::scope_ptr, do not have that semantics. The ownership of the object can be released or passed to other auto_ptr, so the assumption that an object held in an auto_ptr lives for the whole scope of the auto_ptr is bad in itself.
The auto_ptr unambiguously declares that the ownership of the pointer is passed on. The plain pointer isn't self-documenting.
What is the point of an auto-ptr if you only use its internals as a storage location?
Yes, pass it to the function. Or do away with it entirely, if you really don't want it. Presumably the function needs it to pass along ownership to something else.
It sounds like maybe the alternative you're looking for is much simpler:
void ClassA::ExportAnimation(CAnimation &animation) // no pointer
// calling method:
void classB::someMethod()
{
CAnimation animation(1,2); // no pointer
ClassA classAInstance;
classAInstance.ExportAnimation(animation) // no ownership tranfer
... do some more stuff
// object dies here, no earlier, no later
}
Passing the smart pointer to ExportAnimation clearly documents, and enforces, that ownership has been passed to the function, and there is no need for the caller to delete the animation. The function will also not need to explicitly delete the object, just let the pointer go out of scope.
Your suggestion leaves that ambigious; should ExportAnimation delete the object you've passed via raw pointer? You'd need to check the function's documentation to know what the caller should do, and also check the implementation to make sure it's actually implemented as documented.
I would always recommend using smart pointers (and other RAII idioms) to make object lifetime explicit and automatic.