The problem occurs when a new expression of the form new(std::nothrow) C; , where C is the name of the class whose constructor throws. See the code below and a live example using g++ :
#include <iostream> void* operator new(std::size_t size, const std::nothrow_t&) noexcept { void* p; p = malloc(size); std::cout << "operator new(std::nothrow)" << '\n'; return p; } void operator delete(void* p, const std::nothrow_t&) noexcept { free(p); std::cout << "operator delete(std::nothrow)" << '\n'; std::cout << p << '\n'; } class T{}; class C { int i; public: C(int i) : i{i} { std::cout << "C()" << '\n'; throw T{}; } ~C() { std::cout << "~C()" << '\n'; } }; int main() { C* c; try { c = new(std::nothrow) C(3); } catch (T&) { std::cout << "exception thrown in C(int) was caught" << '\n'; std::cout << c << '\n'; } }
g++ displays the following and looks correct:
operator new(std::nothrow) C() operator delete(std::nothrow) 0x13f9c20 exception thrown in C(int) was caught 0
If you use clang , you will get the following output:
operator new(std::nothrow) C() exception thrown in C(int) was caught 0x7fffecdeed00
That is, as if clang does not call operator delete(void*, std::nothrow_t&) defined in the program, and instead calls the operator in the standard library.
It is strange that simply removing the expression std::cout << p << '\n'; in operator delete(void*, std::nothrow_t&) defined in the code, clangs will appear correctly, print:
operator new(std::nothrow) C() operator delete(std::nothrow) exception thrown in C(int) was caught 0x7fffc0ffc000
Edit
In response to the comment from @TC below and others who say that the code above has undefined behavior, I present below another code that shows how the compiler should act in order to correctly compile the fragment above using the pseudocode provided by @TC here . See also this live example . It is important to note that this code does not use the new expression new(nothrow) .
#include <iostream> void * operator new(std::size_t n) { void* p; try { p = malloc(n); } catch (std::bad_alloc&) { throw; } std::cout << "operator new" << '\n'; return p; } void operator delete(void *p) noexcept { free(p); std::cout << "operator delete" << '\n'; } void* operator new(std::size_t size, const std::nothrow_t&) noexcept { void* p = malloc(size); std::cout << "operator new(std::nothrow)" << '\n'; return p; } void operator delete(void* p, const std::nothrow_t&) noexcept { free(p); std::cout << "operator delete(std::nothrow)" << '\n'; std::cout << p << '\n'; } class T {}; class C { int i; public: C(int i) : i{ i } { std::cout << "C()" << '\n'; throw T{}; } ~C() { std::cout << "~C()" << '\n'; } }; int main() { C *c; try { c = (C*)operator new(sizeof(C), std::nothrow); struct cleanup { void* p; bool active; ~cleanup() { if (active) operator delete(p, std::nothrow); } void dismiss() { active = false; } } guard = { (void*)c, true }; new(c) C{1}; guard.dismiss(); } catch ( std::bad_alloc& ) { c = nullptr; } catch (T&) { std::cout << "exception thrown in C() was caught" << '\n'; std::cout << c << '\n'; } }
g++ for this code displays the following:
operator new(std::nothrow) C() operator delete(std::nothrow) 0x10c3c20 exception thrown in C() was caught 0x10c3c20
Surprisingly, clang seems to act correctly with this code, which does not use the new expression new(nothrow) , which clearly shows that when creating this new expression, clang has an error.