How to prevent anyone from stealing my shared_ptr?
So, I use boost::shared_ptr for all the various reference-counting benefits it provides -- reference counting for starters, obviously, but also the ability to copy, assign, and therefore store in STL Containers.
The problem is, if I pass it to just one "malicious" function or object, the object can save the ptr and then I'll never be able to de-allocate it without the foreign funct开发者_开发问答ion or object nicely relinquishing its ownership.
Ultimately, I try to keep object ownership explicit. I accomplish this by having the owner keep the only shared_ptr to the object, and "guest" objects only store weak_ptrs to the object.
I really don't want the "shared" part of shared_ptr, but I'm required to use shared_ptr in order to make weak_ptrs. I want to use scoped_ptr, but it's extremely limited since you can't copy it. You can't store it in a container, you can't lend out weak_ptrs from it, and you can't transfer ownership to a new manager.
What's the solution?
Make it private and provide a facade to do whatever operations needed. Nobody ever sees the pointer. I guess that at that point you would not even need a shared_ptr.
Don't pass around the boost::shared_ptr object... even if you store the object, internally, using a boost::shared_ptr, you should make sure that functions take your object by constant reference rather than a copy of the shared pointer. Since you would need to dereference the shared pointer in order to pass the object to a function that passes by const reference, you will know whether it follows that protocol or not.
It's good enough to use weak_ptr for guest objects, as you described in question. Otherwise you will have a problem with dead pointers.
I would consider to do application rearchitect to remove "malicious" functions/objects or at least fix their behavior.
You could extend the shared_ptr boost class and override delete to force delete the pointer.
The issue really is that, if the library is not releasing or freeing the shared_ptr then its likely to refer to it some time. At this time your application will fall with a SIGSEGV.
I think it totally invalidates the purpose of shared pointers.
The best solution is to fix the library.
Other solution, use AOP to delete pointer on exit of the library function you are calling. This is still likely to break.
There's really no good solution for what you're describing.
You can't use auto_ptr because you're not transferring ownership.
If you can guarantee the owner outlives the references, I'd recommend using a scoped_ptr/store by value in the owner and then passing a raw pointer or reference to those that need it.
If references can outlive the owner (and the references need to be gracefully notified), you have to use shared_ptr/weak_ptr. But, as you stated, you cannot prevent any class/function from locking the weak_ptr and "preventing" deallocation. But, in the interface, do not pass the shared_ptr, pass the weak_ptr. It's only as strong as a convention, but it says "don't hold onto this, it may go away".
If you want to handle your objects in that owner/owned paradigm I recommend doing something like Qt.
- Create a base class Object, which all classes in your system will inherit from. Each object keeps track of its parent/owner and children.
- Use a
setOwner(Object * owner)
method to set the owner and have that method make sure that the owner object is notified about the new child. - The destructor for Object should delete all of the child objects when it is destroyed.
- Define a template class which defines a smart pointer to an Object subclass. Make it so that the Object notifies any connected smart pointers about its destruction so that there values will become NULL when the object is destroyed.
Things to watch out for:
- All objects must be allocated via new for Objects destructor to correctly deallocate them.
- If you forget to set the parent for an object, it'll leak
- Handling objects which don't inherit from Object is tricky, although it can be done by defining a template class which does inherit from Object to hold them.
精彩评论