2

This is implementation of new operator in libstdc++:

_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
  void *p;

  /* malloc (0) is unpredictable; avoid it.  */
  if (__builtin_expect (sz == 0, false))
    sz = 1;

  while ((p = malloc (sz)) == 0)
    {
      new_handler handler = std::get_new_handler ();
      if (! handler)
        _GLIBCXX_THROW_OR_ABORT(bad_alloc());
      handler ();
    }

  return p;
}

Who guarantees that exception in constructor will free the allocated memory?

Upd: thanks to the commentators - actually I meant exception safety of new expression.

  • Could you give an example? From where is the exception thrown - from `new` or from the constructor? What memory - allocated for the object being constructed or some memory allocated within the constructor? – KamilCuk Dec 10 '20 at 13:42
  • 1
    what constructor? new operator just allocates memory, it doesn't construct objects. – bolov Dec 10 '20 at 13:43
  • What constructor? – Asteroids With Wings Dec 10 '20 at 13:44
  • @bolov The *new operator* most certainly calls a constructor (except in the form `new T` for trivial types). The `operator new` *function* doesn’t. Yes, C++ terminology is confusing. – Konrad Rudolph Dec 10 '20 at 13:49
  • As such, it would be best not to use the term "new operator"; indeed, the standard itself only does so passingly, infrequently, and in a way that personally I'd consider a defect. `new` is a keyword, and an expression `new T` is a _new-expression_. – Asteroids With Wings Dec 10 '20 at 13:51
  • We have the "operator new" and the "new expression". The "new expressions" calls "operator new" (except placement new) to allocate memory and then it constructs object(s). I was referring to the operator new (which is presented in the question and doesn't constructs objects). Confusing indeed. – bolov Dec 10 '20 at 13:55
  • Ok, perhaps I'm talking about "new expression", not new operator. How and where the exception safety of new expression is implemented in the code? – Max Dmitrichenko Dec 10 '20 at 14:27
  • @bolov “new expression” = “new operator”. I agree with Asteroids that it’s a confusing term and should better be avoided. But it *is* in common usage, even amongst C++ experts, *including by the C++ standard*. – Konrad Rudolph Dec 10 '20 at 15:29

1 Answers1

5

You are mixing in your question "new expression" and "operator new".

New expression is like this: A* a = new A(); C++ language defines, that this expression is evaluated to something like this (over-simplified pseudo-code):

void* __a = operator new(sizeof(A));
try {
   A::A(this = static_cast<A*>(__a));
} catch (...) {  operator delete (__a); throw; }

As you can see - memory is dealocated if exception happens.

More detailed explanation:

If initialization terminates by throwing an exception (e.g. from the constructor), if new-expression allocated any storage, it calls the appropriate deallocation function: operator delete for non-array type, operator delete[] for array type.


For real generated code by compiler - refer here. You might notice call to operator delete - even if source code does not contain it:

struct A { A(); };
A::A() { throw 13; }

int main()
{
    auto a = new A();
}

Assembler:

 call 401040 <operator new(unsigned long)@plt>
...
 call 401172 <A::A()>
...
 call 401050 <operator delete(void*, unsigned long)@plt>
...
 call 401080 <_Unwind_Resume@plt>
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • But where is the code which implements such a logic? – Max Dmitrichenko Dec 10 '20 at 14:25
  • 4
    It is generated by the compiler – Chris Uzdavinis Dec 10 '20 at 14:27
  • @ChrisUzdavinis so we can tell that any new expression is actually enclosed into try-catch block? Or compiler does it in a different way in this case? I understand that it is implementation defined but let's talk about most popular compilers like gcc or clang? – Max Dmitrichenko Dec 10 '20 at 14:39
  • @MaxDmitrichenko - I added link to example - generated from CompilerExplorer. How it is exactly generated - it is compiler vendor specific. Do not forget - that code in first part of my answer is pseudo-code - do not treat it too serious - it is just illustration - not real world code. – PiotrNycz Dec 10 '20 at 14:51