Reputation: 915
I have read a lot of issues created in regard to this but was not able to answer my question.
I have created a class as follows -
class exampleClass{
public:
exampleClass(int n){
cout<<"Created Class"<<endl;
this->number = n;
}
~exampleClass(){
cout<<endl<<"This class is destroyed Now"<<endl;
}
template<typename t> t
addNum(t a, t b){
return a + b;
}
void print(){
cout<<this->number<<endl;
}
private:
int number;
};
and I make 2 shared_ptr
(or for that matter unique_ptr
, error is same) as follows -
int main(){
exampleClass* object = new exampleClass(60);
std::shared_ptr<exampleClass> p1(object);
std::shared_ptr<exampleClass> p2 (object);
p1->print();
}
Now the error it throws at the end is -
free(): double free detected in tcache 2
Aborted (core dumped)
I am not able to understand why the error at the end. Shouldn't the above code be equal to p2 =p1
(in case of shared_ptr
) or p2 = std::move(p1)
for unique_ptr
as both the pointers are for the same object?
TIA
PS - The title might be a little misleading or not accurate,but I did not know what exactly should be a title.
Upvotes: 0
Views: 726
Reputation: 71
When you create a shared_ptr
from a raw pointer, it takes ownership of the raw pointer, and when the smart pointer goes out of scope, it will call delete on the owned resource. Giving the same raw pointer to 2 different shared_ptr
s causes a double free, as both of them will try to free the resource.
If you need 2 shared_ptr
s that share the same resource, you can copy the first one:
int main(){
exampleClass* object = new exampleClass(60);
std::shared_ptr<exampleClass> p1(object);
std::shared_ptr<exampleClass> p2 = p1;
}
This way they share ownership of the resource (sharaed_ptr
s have an internal reference counter that tracks how many of them own a resource. When you copy a shared_ptr
, the reference counter is incremented. When one goes out of scope, the reference counter is decremented. Only if the counter reaches zero is the resource freed) thus it will only be freed once, when the last shared_ptr
owning the resource goes out of scope.
It's usually preferable to avoid explicitly writing out new
and use make_shared
, which does the allocation, creates the object for you and returns a shared_ptr
that owns it:
auto object = std::make_shared<exampleClass>(60);
Some additional advanced reading in the topic, not strictly related to the question:
make_shared
vs manually calling new
: heremake_shared
with weak_ptr
s and large objects: here (Thanks for bringig this up @Yakk - Adam Nevraumont, this was new for me :))Upvotes: 2
Reputation: 22074
When you create a smart pointer, it will take ownership of the pointer, and deletes it when it goes out of scope (or when the last reference is done in case of a shared pointer). When you create two smart pointers from the same raw pointer they both will delete the pointer at the end of their life, because they don't know about each other.
int main()
{
// Create a shared pointer with a new object
std::shared_ptr<exampleClass> p1 = std::make_shared<exampleClass>(60);
// Now you can safely create a second pointer from your existing one.
std::shared_ptr<exampleClass> p2 = p1;
p1->print();
p2->print();
}
Upvotes: 3