vela18
vela18

Reputation: 37

unique_ptr and failed memory allocation

I want to create a unique pointer using unique_ptr<A>(new A) (not make_unique()).

The unique_ptr constructor is noexcept, however new may throw bad_alloc.

So my question is, whether I should expect an exception calling unique_ptr<A>(new A) in case new fails or not?

I tried to check that and I'm getting 'abort' in the code below, whereas I expected to see "null" on the screen. So it seems, that in case new fails, unique_ptr will throw an exception.

Is that correct?

class A
{
  public:
  int vec[1000000000];
};

int main()
{
  A* a[100000];
  for (int i = 0; i < 100000; ++i)
  {
    a[i] = unique_ptr<A>(new A).release();
    if (!a[i])
    {
      cout << "null" << endl;
      break;
    }
  }
  return 0;
}

Note: The only goal of this code is to cram the memory so that new fails.

Upvotes: 0

Views: 1438

Answers (2)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122133

Suppose you have

void foo(int) noexcept {}
int bar() { throw 42; }

int main(){
    foo(bar());
}

Then foo is not called because already bar() throws.

So it seems, that in case new fails, unique_ptr will throw an exception.

No, the unique_ptr constructor is not being called when new throws.

Upvotes: 2

Remy Lebeau
Remy Lebeau

Reputation: 595742

So my question is, whether I should expect an exception calling unique_ptr<A>(new A) in case new fails or not?

Yes. If new fails, it will throw a std::bad_alloc exception, and the std::unique_ptr object will not even be constructed at all.

I tried to check that and I'm getting 'abort' in the code below, whereas I expected to see "null" on the screen. So it seems, that in case new fails, unique_ptr will throw an exception. Is that correct?

No. new is the one throwing the exception, not the std::unique_ptr constructor (which it can't anyway due to being noexcept, as you noted). Since new is being called outside of the constructor, the constructor being marked as noexcept is irrelevant.

If you want to avoid the std::bad_alloc exception being thrown, use the std::nothrow version of new, eg:

#include <new>

a[i] = unique_ptr<A>(new(nothrow) A).release();

Alternatively, since your use of unique_ptr().release() defeats the whole purpose of std::unique_ptr, just omit it entirely:

a[i] = new(nothrow) A;

Don't forget to delete whatever is successfully new'ed.

Upvotes: 4

Related Questions