https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68210
Bug ID: 68210 Summary: nothrow operator fails to call default new Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- A recent discussion about operator new (https://gcc.gnu.org/ml/gcc-patches/2015-11/msg00192.html) revealed that the libstdc++ implementation of the nothrow overload of the operator doesn't conform to the requirement to "return a pointer obtained as if acquired from the (possibly replaced) ordinary version." The test case below illustrates some of the problems. The requirement quoted above implies that a conforming implementation of the nothrow overload must call the ordinary form like so: void* operator new (size_t n, const nothrow_t&) { try { return operator new (n); } catch (...) { return 0; } } $ cat t.cpp && ~/bin/gcc-5.1.0/bin/g++ -Wall t.cpp && ./a.out #include <new> #include <assert.h> #include <stdlib.h> struct MyBadAlloc: std::bad_alloc { }; static bool new_fail; static bool bad_alloc_thrown; static unsigned new_called; static unsigned new_handler_called; static void new_handler () { if (new_handler_called++) throw MyBadAlloc (); } void* operator new (size_t n) { static size_t cntr; ++new_called; for ( ; ; ) { if (void *p = new_fail ? 0 : malloc (n + sizeof n)) { *static_cast<size_t*>(p) = ++cntr; return static_cast<size_t*>(p) + 1; } if (std::new_handler h = std::set_new_handler (0)) { std::set_new_handler (h); h (); } else { bad_alloc_thrown = true; throw MyBadAlloc (); } } } void operator delete (void *p) { if (p) free (static_cast<size_t*>(p) - 1); } int main () { new_called = 0; void *p = operator new (1, std::nothrow); assert (p != 0); assert (1 == new_called); std::set_new_handler (new_handler); new_fail = true; try { p = operator new (1, std::nothrow); } catch (...) { assert (!"nothrow operator new threw"); } assert (0 == p); assert (2 == new_handler_called); assert (bad_alloc_thrown); } a.out: t.cpp:53: int main(): Assertion `1 == new_called' failed. Aborted (core dumped)