If you need to access non-static members from within Close
you need to bind its this
argument properly
CWrapper() :
m_pHandle(new HANDLE, boost::bind(&CWrapper::Close, this, _1)) {
//code to open handle
}
This, however contains a hidden bug. Your object is copyable, and you bind the deleter to the object of *this
. The handle is associated with the first wrapper you create, but if you copy the wrapper, the handle is shared but associated with the first wrapper, which may not exist anymore:
CWrapper getWrapper() { CWrapper w; return w; }
CWrapper x = getWrapper();
After that code was executed and x
is going to be destroyed, behavior is undefined because x
's destruction of the internal handle pointer will try to use the object bound in w
's constructor invokation - however that object doesn't exist anymore!
A solution to this can be to store the data associated with the handle in the allocated object itself, instead of trying to store it in the toplevel handle object, like in the following code
class CWrapper
{
public:
CWrapper():m_pHandle(new CHandle)
{ }
private:
// This class cannot be copied
class CHandle : boost::noncopyable {
friend class CWrapper;
CHandle()
:m_pHandle(new HANDLE) {
// code to open handle
}
~CHandle() {
// code to close this handle, making use of
// auxilary data for whatever reason
}
private:
boost::scoped_ptr<HANDLE> m_pHandle;
// auxilary data associated with the handle...
};
boost::shared_ptr<CHandle> m_pHandle;
};
The auxilary data is not not stored in the handle anymore, but together with the data that's shared among all copy of the wrapper. The shared data itself is created and destroyed using its normal constructor and destructor.
CWrapper getHandle() { return myHandle; }
CWrapper w = getHandle();
The last wrapper going out of life will destroy the handle, which is explicitly shared among all wrappers.