Two classes A and B share pointer to a third class C and when either A or B are deleted they call delete C as well.
Issue is not observed when only either of A or B is deleted. An exception is getting thrown in this scenario. I have specifically tried to set the class C pointer to NULL and have put in a NULL check to avoid this specific scenario but this null check is somehow not working.
I have read around that shared pointer should be used in this case but I am not sure how to implement it properly. It looks like whole code base needs to be changed to include shared_ptr everywhere as all class C objects would be updated to shared_ptr. Is there a way I can use shared_ptr just to store this pointer without changing all the code?
Edit: I have specifically deleted assignment operator and copy constructor of C to avoid situation both have different pointers due to copying. Can anything else can be done to prevent copying as pointed in answer by john
class A{
C* c;
}
~A(){
if(C != NULL){
delete C;
C = NULL;
}
}
class B{
C* c;
}
~B(){
if(C != NULL){
delete C;
C = NULL;
}
}
CodePudding user response:
A
and B
have separate copies of the pointer to C
. So setting one classes copy of that pointer to NULL
has no effect on the other pointer and you still get a double delete.
You have basically four options
Decide that one class 'owns' the pointer, that class will delete it and the other will not. The danger here is that if the owning class deletes the pointer and then the non-owning class uses the pointer then you are going to get a different kind of error.
Use shared ownership of the pointer, so that it only gets deleted when the last object using it gets destroyed. The easy way to do that is to use
std::shared_ptr
#include <memory> class A { std::shared_ptr<C> c; }; class B { std::shared_ptr<C> c; };
Clone the pointer before copying it to the second class. Something roughly like
a.c = new C(); b.c = new C(*a.c);
this way both classes get separate (but equal) copies of the C
object. But this changes the semantics of your program, maybe you actually want A
and B
to share the same C
object.
This option (suggested by Richard Critten) has class
A
having astd::shared_ptr
and classB
having astd::weak_ptr
. This means thatA
owns theC
object, and when the lastA
object has been destroyed theC
object will also be destroyed. Any remainingB
objects do not prevent the destruction of theC
object but, theB
object can check whether theC
object has been destroyed. In code it looks something like this#include <memory> class A { std::shared_ptr<C> c; }; class B { std::weak_ptr<C> c; }; class C { C(whatever); }; A a; B b; // create a shared pointer a.c = std::make_shared<C>(whatever); // create a weak pointer referring to the same C object b.c = a.c; // create a shared pointer from the weak pointer in b auto c = b.c.lock(); // check if the pointer is valid if (c) { // do something with c c->something(); } else { // c object has been destroyed }