Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are all the ways use_count of std::shared_ptr is incremented?

I have two shared_ptrs pointing to the same int, i.e. calling get() on them returns the same address. But calling use_count() on them returns 1. When the last of them goes out of scope, it tries to free up the memory already freed by the other one, causing a double free runtime error:

#include <memory>
#include <iostream>
using namespace std;

int main() {
    shared_ptr<int> sp1(make_shared<int>(7));
    shared_ptr<int> sp2(&(*sp1));
    cout << sp1.use_count() << endl;  // 1
    cout << sp2.use_count() << endl;  // 1
    cout << sp1.get() << endl;        // same address
    cout << sp2.get() << endl;        // same address
}
// ^ Double free runtime error at closing brace.

Same thing happens in this variant with an explicitly declared raw pointer:

int main() {
    int *raw_ptr = new int(8);
    shared_ptr<int> sp3(raw_ptr);
    shared_ptr<int> sp4(raw_ptr);
    cout << sp3.use_count() << endl;  // 1
    cout << sp4.use_count() << endl;  // 1
    cout << sp3.get() << endl;        // same address
    cout << sp4.get() << endl;        // same address
}
// ^ Double free runtime error at closing brace.

Why does use_count() return 1 (but not 2) if both shared_ptrs point to the same thing? If use_count() returned 1, then why was there the attempt to free the int twice? I thought that a shared_ptr will increase use_count by one if and only if it points to the same address as its brethren shared_ptrs.

Is a std::shared_ptr’s use_count incremented only by the first shared_ptr's construction by raw pointer (or assignment to raw pointer, if default-constructed) and then by additional shared_ptrs’ copy-construction or assignment by any of the prior shared_ptrs? And what are all the other ways of incrementing, if any?

like image 230
CodeBricks Avatar asked Dec 14 '25 06:12

CodeBricks


2 Answers

When you give a pointer to a shared_ptr, that shared pointer takes ownership of that pointer. You are no longer allowed to delete it, pass it to another shared_ptr, or similar. There's no global lookup table for the new shared_ptr to check to find that there's already another shared_ptr that already owns the pointer or anything like that.

Put another way, the double free error occurred when the second shared_ptr was created by passing in the same pointer rather than copying the shared_ptr itself (which increments the use count). The fact that you can't observe the undefined behavior until later doesn't change where it actually occurs.

like image 188
Billy ONeal Avatar answered Dec 16 '25 22:12

Billy ONeal


You should use a copy constructor of shared_ptr to construct the second shared pointer properly.

like image 28
kraskevich Avatar answered Dec 16 '25 21:12

kraskevich



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!