32
votes

I just realised reading this page that the constructor of std::shared_ptr with a single pointer argument is not noexcept.

Hence the following code contains a possible memory leak:

std::shared_ptr<int> p3 (new int);

The reasonning is that two allocations could occure:

  • The first one before the call to the constructor
  • The second one in the constructor of shared_ptr (This is what happens in VS 2012 for example)

Two questions here:

Is it true that if the second allocation throws an exception, the memory of the first one leaks ?

If the answer is yes:

what is the correct idiom to use std::shared_ptr?

  • using make_shared
  • giving the ownership of the first allocation to a std::unique_ptr then transfering the ownership
  • Other thoughts ?
2
Oh my, an interesting question about smart pointers. I thought this was not possible any more. +1R. Martinho Fernandes
The other reference already had the answer to this...Cubbi

2 Answers

30
votes
template<class Y> explicit shared_ptr(Y* p);

[util.smartptr.shared.const]/6 Throws: bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.
[util.smartptr.shared.const]/7 Exception safety: If an exception is thrown, delete p is called.

So no, no memory leak.

12
votes

Late answer, but it is better to use make_shared() for exception safety, as outlined in GotW #102: The following code is not exception safe:

 f( std::shared_ptr<T1>{ new T1 }, std::shared_ptr<T2>{ new T2 } );

Whereas the following is:

f( std::make_shared<T1>(), std::make_shared<T2>() );