https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69879
--- Comment #10 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Daniel Gutson from comment #0) > This issue comes from the following discussion: > > https://gcc.gnu.org/ml/libstdc++/2015-11/msg00009.html > > In short: Pedro Alves suggested as a solution the addition of a pointer to > the original (default) operator new and another for the operator delete, > e.g. __default_operator_new and __default_operator_delete. > This will allow users to override the global operators new and delete, and > yet call the original implementations, for example to alter the behavior > when there is no memory and the nothrow new should not iterate calling the > new_handler. Re-reading that thread, I'm not really convinced by the motivation. the requirement is based on a fairly convoluted set of self-imposed conditions. Since PR 68210 was fixed, the no-throw versions of operator new are now coupled to the throwing operator new. That means you only need to replace one version of new/delete and the others will use it. So we probably don't need to expose a __default_operator_xxx pointer for every overload now. Also, the original problem described in https://gcc.gnu.org/ml/libstdc++/2015-11/msg00009.html should no longer exist. The new-handler should simply throw when it can't make more memory available (as required by the standard), and that will cause the nothrow operator new to return null. There is a tangential problem though, which I am interested in. ince PR 68210 was fixed, when libstdc++ itself is built with -fno-exceptions then failure to allocate will abort the process, even if you use the nothrow operator new. I'm interested in a solution that allows operator new(nothrow_t, size_t) to return null when built with -fno-exceptions. One approach might be for operator new(nothrow_t, size_t) to detect when operator new(size_t) has been replaced (which might involve comparing its address with something like __default_operator_new_throw, and if the addresses are the same (i.e. the user hasn't replaced operator new) then do the work directly instead of calling operator new(size_t), but return null instead of throwing. That would make new(nothrow) useful again in environment where even libstdc++ is built with -fno-exceptions. Also, the alternative implementation of operator new(nothrow_t, size_t) could potentially use a different type of new-handler, which could be used to get the behaviour that motivated this bug report and the thread above. So something like this in libsupc++/new_opnt.cc using __nothrow_new_handler = bool(*)(); extern __nothrow_new_handler __nt_new_handler; _GLIBCXX_WEAK_DEFINITION void * operator new (std::size_t sz, const std::nothrow_t&) noexcept { #if __cpp_exceptions // _GLIBCXX_RESOLVE_LIB_DEFECTS // 206. operator new(size_t, nothrow) may become unlinked to ordinary // operator new if ordinary version replaced __try { return ::operator new(sz); } __catch (...) { return nullptr; } #else // no-exceptions if ( /* operator new has been replaced */ ) return ::operator new(sz); // otherwise, do the allocation directly so we can return null on failure void *p; /* malloc (0) is unpredictable; avoid it. */ if (__builtin_expect (sz == 0, false)) sz = 1; while ((p = malloc (sz)) == 0) { if (__nt_new_handler && __nt_new_handler()) continue; // retry new_handler handler = std::get_new_handler (); if (! handler) return 0; handler (); } return p; #endif } This would allow a program to set a non-standard handler that doesn't have to throw or terminate if it can't make memory available, causing the nothrow-new to return null, which was the original aim. I think something like this would solve the original problem, but *also* make nothrow-new more useful for people who aren't installing new-handlers.