I have a class that contains a vector of object pointers. I have a GetObject(..) function in that class that looks through the vector, finds the object desired, and returns a pointer to it. However, if the user of the class does a delete() on that returned pointer, my program will crash because the vector still has a pointer to that, now invalid, object. So, in my GetObject() class, I can return a const pointer, but that doesn't solve the problem because you can still delete the object. The object is mutable so I can't return a pointer to a const object. I suppose I could prevent deletion by returning a reference to the object but I have my function returning NULL if there is an error. I guess I can pass back the object reference via the parameters and then return and error number like this
//-1 on object on found. 0 for success. Object is passed back in
// the function parameter result.
int MyObject::GetObject(int object_id, Item& result)
Is this the best solution for such a situation?
The best way to solve this problem is to use a shared-ownership smart pointer like shared_ptr, which you can find in Boost, C++ TR1, and C++0x.
A smart pointer is a container that manages the lifetime of your dynamically allocated object for you. It takes responsibility for deleteing the object when you are done using it.
With a shared ownership smart pointer, you can have multiple smart pointers that all share ownership of the dynamically allocated object. A reference count is kept that keeps track of how many smart pointers have ownership of the object, and when the last owning smart pointer is destroyed, the dynamically allocated object is deleted.
It is extremely difficult to manage resources manually in C++, and it's very easy to write code that looks correct and works right most of the time but that is still not correct. By using smart pointers and other resource-owning containers (like the standard library containers), you no longer have to manage resource manually. It is significantly easier to write correct code when all of your resource management is automatic.
Automatic resource management in C++ is accomplished using a design pattern called Resource Acquisition is Initialization (RAII), which is arguably the most important design pattern you as a C++ programmer should become familiar with.
Anybody in your code could also try to de-reference NULL. You going to stop them doing that too? If your container owns the object, and you make this clear (returning a raw pointer is usually pretty clear or mention in docs), then anyone who deletes it, the result is their own fault. The only way that you could guarantee the prevention of the deletion of the object is to prevent the user from ever gaining a native reference or pointer - in which case they just can't access the object.
Who are clients of your class? If they are not your mortal enemies you could just ask them nicely not to delete the object. Otherwise, there will always be a way for "them" to mess you up.
Okay, one possible solution is to make destructor private. That will prevent everyone from deleting the object. But then the object has to delete itself (delete this) somehow, maybe through some function called DeletObjectButDontBlameMeIfAppCrashes. If the owner is some other class then you can set the destructor to protected and owner class as friend of this class.
You should return a reference to the object. There are two ways to handle the case when there is no object found.
First, you can use the Null Object Pattern in order to implement a special value for that case. That might not make sense for your case though.
The other way is to split it up into two methods, one which can be used to check if an appropriate element exists, and one to retrieve it.
Many STL-containers or algorithms implement both of these, either by returned a past-the-end iterator, or by having empty() returns false as a prerequisite of calling a method like front or back.
If you can use the boost libraries, smart pointers can be used to ensure that pointers stay valid. Essentially, each reference to a smart pointer increases its "use count" by 1. When the reset function is called on a reference, the reference goes away and the use counter decrements. As long as some object is still holding on to a smart pointer, the reference will be valid. Note that the other classes will be able to change what its pointing to, but can't delete it.
(My description deals mainly with smart pointers specifically - the different types of pointers vary a little, but the general idea remains the same).
Related
I have a set of objects in a vector of pointers to their baseclass held inside a manager:
std::vector<object*> objectVec;
Classes may wish to spawn one of these objects using the Add() method in the manager. The problem is that they then subsequently need to set or update these objects themselves. I've decided to have Add() return a pointer to the object itself, which is stored in whatever class has decided to spawn one. The problem is dealing with the case where the object behind that pointer may have been deleted.
Add looks like this:
object* ObjectManager::Add(object* obj)
{
objectVec.push_back(obj);
return objectVec.back();
}
and used like this:
objectptr = ObjectManager::OMan()->Add(new object());
Where objectptr is a member of whatever class has called the function. So should that particular object be deleted, the pointer returned by Add would point to rubbish.
Is it my responsibility to ensure that whateverclass::objectptr is always set to NULL if this object is deleted? Or can this be dealt with using some sort of smart pointer? The problem being that I don't need to use a smart pointer to deal with the possibility of a memory leak, but to deal with the case where the stored pointer has become invalid.
Please let me know if i've been unclear, or if the question is badly formed.
Any help would be greatly appreciated.
Yes, you can store smart ptr's instead of raw ptr's in your vector. In this case if somebody releases an object, it's not deleted until the last reference is not released (the one held in vector in your case). You can use boost::shared_ptr or std::shared_ptr (C++11).
If this is not what you want, you can use boost::weak_ptr to store references in your vector. weak_ptr doesn't increment reference counter so if somebody releases an object, it's get deleted, but reference (weak_ptr) stored in your vector allows you to check this.
You likely want weak_ptr and shared_ptr. shared_ptr is a general smart pointer class. weak_ptr is an observer of shared_ptr. When all the references of the shared_ptr go away, instances of weak_ptr "become null" and are easier to deal with than a pointer to a deleted object.
These classes come with Boost.
http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/shared_ptr.htm
http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/weak_ptr.htm
And if I'm not mistaken, there are equivalents built into std namespace on compilers that implement newer C++0x standards. Visual C++ keeps has this built in.
http://blogs.msdn.com/b/vcblog/archive/2011/02/16/10128357.aspx
Oh shoot, looks like everyone else beat me to the answer...
Best is to forget this "manager" idea, but if you do or if you don't, the solution to shared ownership is the same as always, use boost::shared_ptr.
Or, with relatively new compiler, use std::shared_ptr.
Considering that with shared_ptr the ownership issue is taken care of already, then ask yourself, what is it that the "manager" manages?
Cheers & hth.,
Is it my responsibility to ensure that whateverclass::objectptr is always set to NULL if this object is deleted?
You're writing the class, so it's up to you to decide. This is a design decision and either choice is admissible, provided that you document it:
design the application
write the documentation/specification
write the code to matches the specification
Or can this be dealt with using some sort of smart pointer?
Using a smart pointer (strong or weak version) will help achieve whatever behavior you chose for the class. However, it will also strongly affect the client code. In the following code:
class Scene
{
// can't use this object in a call to `ObjectManager::Add()`,
// assuming it uses a smart pointer to deal with object lifetimes.
Object myLight;
};
The use cases for the ObjectManager class should be taken into consideration, on top of simplicity of implementation. Think "write once, use a lot".
Dangling pointers and memory leaks are two different issues, but a proper shared pointer can protect from both. For this particular case, I'd suggest boost::shared_ptr.
Use std::vector<boost::shared_ptr<BaseType>> for the vector type and also have the objects that hold the bare pointers now hold instead a boost::shared_ptr<BaseType>. This will ensure that the pointers will stay valid in the vector and in the objects as long as one of those objects still exist.
If you have differing requirements, you can use a boost::weak_ptr in one of the places holding the pointer (either the vector or the object).
Also, the object can hold a derived type instead of a base type (boost::shared_ptr<DerivedType>) and you can convert between them using boost::shared_static_cast.
Here is the documentation for all of these concepts.
I'm wondering if anyone's run across anything that exists which would fill this need.
Object A contains an object B. It wants to provide access to that B to clients through a pointer (maybe there's the option it could be 0, or maybe the clients need to be copiable and yet hold references...whatever). Clients, lets call them object C, would normally, if we're perfect developers, be written carefully so as to not violate the lifetime semantics of any pointer to B they might have...but we're not perfect, in fact we're pretty dumb half the time.
So what we want is for object C to have a pointer to object B that is not "shared" ownership but that is smart enough to recognize a situation in which the pointer is no longer valid, such as when object A is destroyed or it destroys object B. Accessing this pointer when it's no longer valid would cause an assertion/exception/whatever.
In other words, I wish to share access to data in a safe, clear way but retain the original ownership semantics. Currently, because I've not been able to find any shared pointer in which one of the objects owns it, I've been using shared_ptr in place of having such a thing. But I want clear owneship and shared/weak pointer doesn't really provide that.
Would be nice further if this smart pointer could be attached to member variables and not just hold pointers to dynamically allocated memory regions.
If it doesn't exist I'm going to make it, so I first want to know if someone's already released something out there that does it.
And, BTW, I do realize that things like references and pointers do provide this sort of thing...I'm looking for something smarter.
boost::weak_ptr is what you are looking for. Maybe with some minor tweaks though, like prohibiting creation of shared_ptr from it. Also, this can hold anything, including pointer to memory that is not dynamically allocated.
The semantics you want is similar to Qt's QPointer. This is a pointer that can hold QObjects and nulls itself when the corresponding QObject is deleteed (ordinarily, eg. by operator delete).
However, similar approach has inherent problems - such that the client cannot be sure he isn't using a dangling pointer. eg.
QPointer<T> smart_ptr = original_obj;
T* tmp = smart_ptr; // this might be a function argument etc.
... // later
delete original_obj;
... // even later
tmp->do_something(); // CRASH
This can be avoided using some "hard" references that don't allow object deletion, which is exactly what shared_ptr/weak_ptr do.
BTW, AFAIK, shared_ptr can point to member variables, except it can't manage them. That is, you must provide a custom deleter that doesn't do anything.
I have a piece of C++ classes and I have the raw pointer to the objects. The pointer to the object would get passed down to the function. The problem is the underlying function might need to store the pointer at times in an STL container in which pointer to the object would be used later on. If I am not using shared_ptr, I am thinking of adding a bool flag to the class which indicates whether the caller of the function is responsible for deleting the object memory. Would that be fine?
Thanks.
Messy. And rife with many potential bugs that will keep you at work well past midnight on a Saturday.
Be clear and consistent about resource ownership. Either the vector owns the pointers, or some specific function owns the pointers, or smart pointers own pointers. Any mixing of these semantics will have the ultimate result of you tearing your hair out late at night.
The best solution is usually to use a reference-counted smart pointer. (As you probably already know all to well, you can't use std::auto_ptr) Barring that, create a class whose sole purpose in life is to allocate, deallocate and grant access to the vector's contained pointers. Any function that needs the contained object would go through your manager class to get to them.
STL containers will almost certainly take a copy of the object which you insert into it. When the object is removed from the container, the object will be destroyed.
If the default copy constructor is not sufficient (i.e. you need to do a deep copy of the object), you need to ensure you implement your own version which does the copy properly.
I have some intermittent segmentation faults in a Qt application. I think the problem is related to our (bad) use of QSharedPointer. The Qt Documentation states :
QSharedPointer::QSharedPointer ( T * ptr ) :
Creates a QSharedPointer that points to ptr. The pointer ptr becomes managed by this QSharedPointer and must not be passed to another QSharedPointer object or deleted outside this object.
I think we are doing both must not... :/
Is there a OOP way to enforce that the pointer managed by QSharedPointer cannot be deleted or passed to another QSharedPointer?
The best solution will be to have a compiler error.
The normal pattern is to put the new statement inside the smart pointer's constructor, like this:
QSharedPointer<Obj> p (new Obj(2));
That way you never have a reference to the naked pointer itself.
If you refactor your code so that all new operator are in lines like these, all your problems will be solved.
Well, an OOP-esque way would be to create the raw pointer as a private member in a wrapper class, and only perform actions on the pointer through methods that act on the shared pointer. kind of silly though, isn't it?
Or you could make your class with the raw pointer a base class to your other classes and make the raw pointer a private member in the class. In this regard, you're more or less creating an abstract class that does nothing. Your derivative classes must instead do all the work, and since they can't access the raw pointer, compilation will fail... this doesn't stop someone from just copying the raw pointer value out of the shared pointer, though.
In the end, I think your best policy is to manuall change all of the functions in question to use either a shared pointer or else a raw pointer. You can copy one shared pointer to another safely, so why no just go that way?
Edit:
I might add that regardless of whether or not you're using shared pointers, it sounds like you're having ownership issues. If a pointer was created in one scope, it should be deleted in that scope, unless the function that it is passed to contractually takes ownership of the pointer. Using a shared pointer in this scenario will only caused different bugs, eventually. It sounds like you have design issues deeper than just the sharing of pointers.
I'm not familiar with the particular Qt implementation of a shared pointer, but as a general guideline : attempting to mix raw pointers with managed pointers usually ends in blood. Once you 'trust' a shared pointer implementation in taking ownership of your dynamically allocated data, you should under no circumstances try to manage the object lifetime yourself (for example by deleting the provided pointer).
Is there a OOP way to enforce that the pointer managed by QSharedPointer cannot be deleted ?
I guess you could imagine some weird technique where the pointed type would have a private destructor and declare QSharedPointer as friend (which would effectively prevent any 'outside deletion' from compiling), but I wouldn't bet that anything good can come out of this (and note that it will make your type absolutely unusable unless new'ed and transfered to a QSharedPointer).
Is there a OOP way to enforce that the pointer managed by QSharedPointer cannot be passed to another QSharedPointer?
I can't think of any, and that is another reason why you should avoid manipulating the raw pointer once it's ownership has been transferred to a QSharedPointer.
Check your code for all .data() usage and make sure what they return is neither stored nor deleted. I don't think a hard compiler error would be good, because sometimes it's okay to pass the raw pointer, e.g. to a function that doesn't store nor delete passed pointers. (Especially when using 3rd-party code, you cannot always change everything to use shared pointers, and often you want it to work with both, raw and shared ptrs).
One could mark QSharedPointer::data() as deprecated (by patching Qt), to get a compile time warning.
How should I avoid using the "this" pointer in conjunction with smart pointers? Are there any design patterns/general suggestions on working around this?
I'm assuming combining the two is a no-no since either:
you're passing around a native pointer to a smart pointer-managed object which defeats the point of using the smart pointers in the first place,
if you wrap the "this" pointer in a smart pointer at use, e.g. "return CSmartPtr(this);", you've effectively set up multiple smart pointers managing the same object so the first one to have a reference count of zero will destroy the object from under the other, or
if you have a member variable holding the value of CSmartPtr(this) to return in these cases, it'll ultimately be a circular reference that results in the reference count always being one.
To give a bit of context, I recently learned about the negative implications of combining STL containers with objects (repeated shallow copying, slicing when using containers of a base class, etc), so I'm replacing some usage of these in my code with smart pointers to the objects. A few objects pass around references to themselves using the "this" pointer, which is where I'm stuck.
I've found smart pointers + “this” considered harmful? asked on a somewhat similar problem, but the answer isn't useful as I'm not using Boost.
Edit: A (very contrived) example of what I'd been doing would be
...::AddToProcessingList(vector<CSmartPtr> &vecPtrs)
{
vecPtrs.push_back(CSmartPtr(this));
}
Combining the two can be done, but you always need to keep clear in your mind about the ownership issues. Generally, the rule I follow is to never convert a raw pointer to a smart pointer (with ownership), unless you are sure that you are taking ownership of the object at that point. Times when this is safe to do should be obvious, but include things like:
you just created the object (via new)
you were passed the object from some external method call where the semantic is obviously one of ownership (such as an add to a container class)
the object is being passed to another thread
As long as you follow the rule, and you don't have any ambiguous ownership situations, then there should be no arising issues.
In your examples above, I might look on them as follows:
you're passing around a native pointer to a smart pointer-managed object which defeats the point of using the smart pointers in the first place
In this case, since you are passing around the native pointer, you can assume by my rule that you are not transferring ownership so you can not convert it to a smart pointer
if you wrap the "this" pointer in a smart pointer at use, e.g. "return CSmartPtr(this);", you've effectively set up multiple smart pointers managing the same object so the first one to have a reference count of zero will destroy the object from under the other
This is obviously illegal, since you have said that the object is already owned by some other smart pointer.
if you have a member variable holding the value of CSmartPtr(this) to return in these cases, it'll ultimately be a circular reference that results in the reference count always being one.
This can actually be managed, if some external code implicitly owns the member variable - this code can call some kind of close() method at some point prior to the object being released. Obviously on reflection, that external code owns the object so it should really have a smart pointer itself.
The boost library (which I accept you have said you are not using) makes these kind of issues easier to manage, because it divides up the smart pointer library along the different types of ownership (scoped, shared, weak and so on).
Most smart pointer frameworks provide a means around this. For instance, Boost.SmartPtr provides an enable_shared_from_this<T> CRTP class which you use as a base class, and then you can make sure your shared pointer doesn't result in two pointers to the same object.
One fairly robust solution to this problem is the use of intrusive smart pointers. To instantiate RefCountedPtr<T>, T should derive from RefCount. This allows construction of RefCountedPtr<T> from this, because this->RefCount::m_count holds the single counter that determines the lifetime.
Downside: you have an unused RefCount when you put the object on the stack.