This question already has answers here:
How can I determine if a C++ object has been deallocated?
(6 answers)
Closed 4 years ago.
I have pointers in a module (Let's call module A) to store all objects (in module B) I want to access. It works fine.
When dynamic creation/deletion function is added for those objects (in module B). Creation is fine while deletion gives problems that my pointers are not valid any more.
Is there any easy way for check if the object pointed by pointers are still valid? (I can think of to add functions in destructor of objects in Module B to notify module A for updates, but this is not that easy)
No. You have to manage the lifetime of the object somehow.
Fortunately, the C++ standard library gives us tools to do this: use std::shared_ptr for pointers that can share ownership of an object and std::weak_ptr for pointers that point at something managed by shared pointers but do not participate in the ownership sharing scheme themselves.
(also, use std::unique_ptr when that is appropriate)
No, in general there is no way to test if a (raw) pointer points to a valid object or not.
Only case where you know a pointer doesn't point to a valid object for sure is if it's value is null. So, if you always set a pointer to null after deleting the pointed object, then you can check the validity by testing nullness. Of course, this quickly becomes unbearable if you ever make copies of the pointer.
It's much easier to guarantee the validity by using smart pointers. Objects pointed by only shared_ptr or only unique_ptr will never be deleted as long as you're pointing at it. Unless the object is silly and calls delete this.
Related
This question already has answers here:
C++ Is it possible to determine whether a pointer points to a valid object?
(6 answers)
Closed 9 months ago.
I was reading C++ Is it possible to determine whether a pointer points to a valid object? and the correct answer in this thread is that no, you can't do that, but the thread is quite old now and I wanted to know if anything has changed. I read that with smart pointers that would be possible. So how could that be achieved?
Is it possible to determine if a pointer points to a valid object
No, it isn't generally possible to determine whether a pointer points to a valid object.
I wanted to know if anything has changed
Nothing has changed in this regard.
I read that with smart pointers that would be possible. So how could that be achieved?
Unless you misuse it in a bad way, a smart pointer is never invalid. As such, there is no need to check whether it is valid or not. It should either be null or point to a valid object.
Weak pointer is a special kind of smart pointer that doesn't own an object directly, but it points to an object owned by shared pointer(s). The pointed object may be destroyed when no shared pointer points to it anymore. It's possible to ask the weak pointer whether that has happened or not. This state is somewhat analogous to being invalid, except the state is verifiable.
So how could that be achieved?
You can std::make_unique or std::make_shared to create a dynamic object owned by a smart pointer. The choice between them depends on what kind of ownership you need: unique or shared. Weak pointers can be created only from shared pointers.
I'm rather inexperienced with pointers and I'm having trouble with the difference between a simple pointer and a std::shared_ptr. I want to use a shared_ptr so I don't have to be so careful about deleting the object when nothing points to it.
I am having trouble with a library/header I'm using (easylogging++). I don't think it is a problem with the external library, but with my use of pointers. The library has a function that returns a simple pointer to an object. I always convert the simple pointer to shared_ptr and that is where the trouble happens.
// Works fine---but I want a shared_ptr
Object* MyInstance(ReturnPointerToObject(...));
// Compiles fine, but crashes during deallocation of the Object (Seg fault?)
std::shared_ptr<Object> MyInstance(ReturnPointerToObject(...));
My program crashes when things are being deallocated at the end of the program.
Questions:
Is converting a pointer to shared_ptr like this a good or a bad idea?
Is it a problem with the external library I'm using?
Do I simply not understand pointers and shared pointers?
When you construct a shared_ptr to an object (from anything other than an existing shared_ptr or weak_ptr to that object) you are creating a new scheme to manage the object's lifespan. If something else already controls that object's lifespan, then this is an utterly broken thing to do. If, for example, ReturnPointerToObject returns a pointer to someone else's object, you have no right to control the object's lifespan, and thus creating a shared_ptr to it is broken behavior and will result in delete being called erroneously.
I would also just advise against using shared_ptr where you don't actually need a shared pointer. The C++ way is that you don't pay for what you don't use, and other mechanisms (such as unique_ptr) exist for cases where sharing aren't needed. You are, of course, right to adopt a policy of avoiding naked pointers wherever possible.
This question already has answers here:
Which kind of pointer do I use when?
(4 answers)
C++ 11: smart pointers usage [duplicate]
(1 answer)
Closed 9 years ago.
From c++ 11 i can write code without create and deleting raw pointers.
But is it the right way to go- Should i always use smart pointers (either shared, unique or weak) or are there situations in which i should delete objects by myself?
It is hard to imagine situations where you would want to manually delete an object, so in that sense, the answer to your question is "yes, always use smart pointers".
However, raw pointers do have another use case. Smart pointers are all about conferring ownership semantics. A unique_ptr has exclusive ownership of the object it points to, and will destroy the object when the pointer goes out of scope. A shared_ptr implements shared ownership, and the object will be destroyed when the last shared pointer goes out of scope.
Raw pointers are still useful for cases where you want to point to an object without indicating any kind of ownership. You're just pointing to an object you know exists, and that someone else (who owns it) will delete it when the time comes.
Raw pointers are for pointing to objects. Smart pointers are for owning objects.
There are really very few cases where you'd want to use a smart
pointer. In most applications, either most deletes will be
delete this, or if the application is transactional, the
transaction manager will take care of the delete. In cases
where this doesn't apply, you generally don't want to use
dynamic allocation to begin with. About the only times you'll
use smart pointers:
For some reason or another, you cannot make the object fully
operational in the constructor, but have to follow up with
additional actions before it is active. In this case, it makes
sense to keep it in an std::unique_ptr until the object is
fully active, then call release.
You really want value semantics, but you also need
polymorphism. In this case, use some sort of shared pointer.
(But beware of cycles.) If the object is mutable, beware too,
since you'll end up with reference semantics.
You really want value semantics (with deep copy), but the
profiler shows that the cost of copying is too high, you might
also consider some sort of shared pointer. This has its
dangers, but for large blocks of immutable data, can be a good
solution.
But for starters, you should always ask yourself: why am
I allocating this object dynamically. The most frequent valid
reason is that it is an entity object, with a lifetime defined
by program logic (i.e. its lifetime ends as a result of some
external event). In such cases, smart pointers will cause more
problems than they solve.
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 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).