shared_ptr doesn't free memory when the counter reaches 0

Hi.

I'm trying to implement my own shared_ptr class for training purposes.
But first, I need to better understand how shared_ptr works.

Consider this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main()
{
   int* ptr = new int{ 5 };

   {
	shared_ptr<int> shared{ ptr };
	cout << shared.use_count() << endl;
   }

    // I expect the resource handled by 'ptr' to be freed here 

    cout << *ptr;

    // Instead, I still get printed 5!

    return 0;
} 


shared_ptr is created inside of a strictly scoped area { } and it's getting the resource pointed by ptr.

After the shared_ptr goes out of scope, the area pointed by ptr should've been released... but apparently that didn't happen.

Why?
Last edited on
> I expect ... Instead, I still get printed 5!

Trying to access an object after its lifetime has ended and storage occupied by it has been released engenders undefined behaviour.

To verify that the deleter is called, give the shared pointer a noisy deleter.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <memory>

int main()
{
   int* ptr = new int{ 5 };
   std::cout << "ptr == " << ptr << '\n' ;

   {
       const auto deleter = []( int* p ) { std::cout << "delete " << p << '\n' ; delete p ; } ;
	   std::shared_ptr<int> shared{ ptr, deleter  };
	   std::cout << shared.use_count() << '\n' ;
   }
}

http://coliru.stacked-crooked.com/a/c7dc517dbf5ea195
http://rextester.com/DQHJT75876
Thanks for the reply.

I read that using

 
shared_ptr<Object> p1 = make_shared<Object>(123);


is better than

 
shared_ptr<Object> p1{ new Object(123) };


Can you tell me why?

I already found something on the internet, but I don't get it well
The constructor shared_ptr<T>( U* ptr ) ; is exception safe in isolation. If the constructor of the shared pointer throws - typically, because of allocation failure for the shared control block - delete ptr ; is called before the exception is propagated.

However,
code such as f(std::shared_ptr<int>(new int(42)), g()) can cause a memory leak if g throws an exception because g() may be called after new int(42) and before the constructor of shared_ptr<int>. This doesn't occur in f(std::make_shared<int>(42), g()), since two function calls are never interleaved.
http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared


In addition, there may be (in practice, there is) a performance benefit:
std::make_shared<T> typically allocates memory for the T object and for the std::shared_ptr's control block with a single memory allocation (this is a non-binding requirement in the Standard), where std::shared_ptr<T>(new T(args...)) performs at least two memory allocations.
http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared
alright, what I don't understand is:

make_shared<T> typically allocates memory for the T object and for the std::shared_ptr's control block with a single memory allocation (this is a non-binding requirement in the Standard), wherestd::shared_ptr<T>(new T(args...)) performs at least two memory allocations

how can make_shared() be more efficient than a single constructor?

why does shared_ptr makes two allocations? what are these allocations for?
make_shared() is better than the shared_ptr assignment, as it eliminates unnecessary copies.
> why does shared_ptr makes two allocations? what are these allocations for?

Consider: std::shared_ptr<T> ptr(new T(args...) ) ;

One allocation is in the client code, for the object of type T new T(args...)

At least one (typically one) other allocation is required for the shared control block associated with the shared pointer.

The shared_ptr objects that own a resource share a control block. The control block holds:

. the number of shared_ptr objects that own the resource,
. the number of weak_ptr objects that point to the resource,
. the deleter for that resource if it has one,
. the custom allocator for the control block if it has one.

https://msdn.microsoft.com/en-us/library/bb982026.aspx
Topic archived. No new replies allowed.