Replace std::__throw_bad_alloc call with standard C++ (#2900)

* Replace std::__throw_bad_alloc call with standard C++

Since December of 2025, std::__throw_bad_alloc is no longer visible
through #include <new> causing jemalloc build failures with gcc 16.
As far as I can tell, all std::__throw_bad_alloc did was arrange to
raise a std::bad_alloc exception if exceptions are enabled.  I am not
sure whether its usage was truly meaningful in jemalloc since the call
is wrapped in a try catch and any usage of try catch is considered an
error when compiling with -fno-exceptions on gcc, at least.

This change adds a check to configure.ac that determines whether
exceptions are enabled by compiling a simple try catch that raises a
std::bad_alloc exception.  If that test succeeds, the macro
JEMALLOC_HAVE_CXX_EXCEPTIONS is defined, and jemalloc will raise an
exception.  Otherwise, we call std::terminate() to abort.

This was tested on FreeBSD with the gcc16 port with and without exceptions
enabled.

* Replace std::set_new_handler calls with std::get_new_handler

Previously, std::set_new_handler was used as a workaround for
compilers with only partial support for C++11.  Now that C++14 is a
requirement to enable C++ support, we can assume std::get_new_handler
is available.
This commit is contained in:
lexprfuncall
2026-04-27 11:50:27 -07:00
committed by GitHub
parent bb0a6aca10
commit 1a15fe33a4
4 changed files with 43 additions and 14 deletions

View File

@@ -337,9 +337,11 @@ TESTS_INTEGRATION += \
endif endif
ifeq (@enable_cxx@, 1) ifeq (@enable_cxx@, 1)
CPP_SRCS := $(srcroot)src/jemalloc_cpp.cpp CPP_SRCS := $(srcroot)src/jemalloc_cpp.cpp
TESTS_INTEGRATION_CPP := $(srcroot)test/integration/cpp/basic.cpp \ TESTS_INTEGRATION_CPP := $(srcroot)test/integration/cpp/basic.cpp
$(srcroot)test/integration/cpp/infallible_new_true.cpp \ ifeq (@enable_cxx_exceptions@, 1)
TESTS_INTEGRATION_CPP += $(srcroot)test/integration/cpp/infallible_new_true.cpp \
$(srcroot)test/integration/cpp/infallible_new_false.cpp $(srcroot)test/integration/cpp/infallible_new_false.cpp
endif
else else
CPP_SRCS := CPP_SRCS :=
TESTS_INTEGRATION_CPP := TESTS_INTEGRATION_CPP :=

View File

@@ -374,7 +374,30 @@ fi
if test "x$enable_cxx" = "x1"; then if test "x$enable_cxx" = "x1"; then
AC_DEFINE([JEMALLOC_ENABLE_CXX], [ ], [ ]) AC_DEFINE([JEMALLOC_ENABLE_CXX], [ ], [ ])
fi fi
if test "x$enable_cxx" = "x1"; then
dnl Now check whether the C++ compiler has exceptions enabled.
AC_LANG_PUSH([C++])
SAVED_CXXFLAGS="${CXXFLAGS}"
CXXFLAGS="${CXXFLAGS} ${EXTRA_CXXFLAGS}"
JE_COMPILABLE([C++ exception support], [
#include <new>
], [
try {
throw std::bad_alloc();
} catch (const std::bad_alloc &) {
}
], [je_cv_cxx_exceptions])
CXXFLAGS="${SAVED_CXXFLAGS}"
AC_LANG_POP([C++])
if test "x${je_cv_cxx_exceptions}" = "xyes" ; then
AC_DEFINE([JEMALLOC_HAVE_CXX_EXCEPTIONS], [ ], [ ])
enable_cxx_exceptions="1"
else
enable_cxx_exceptions="0"
fi
fi
AC_SUBST([enable_cxx]) AC_SUBST([enable_cxx])
AC_SUBST([enable_cxx_exceptions])
AC_SUBST([CONFIGURE_CXXFLAGS]) AC_SUBST([CONFIGURE_CXXFLAGS])
AC_SUBST([SPECIFIED_CXXFLAGS]) AC_SUBST([SPECIFIED_CXXFLAGS])
AC_SUBST([EXTRA_CXXFLAGS]) AC_SUBST([EXTRA_CXXFLAGS])

View File

@@ -465,6 +465,9 @@
/* Is C++ support being built? */ /* Is C++ support being built? */
#undef JEMALLOC_ENABLE_CXX #undef JEMALLOC_ENABLE_CXX
/* Are C++ exceptions enabled? */
#undef JEMALLOC_HAVE_CXX_EXCEPTIONS
/* Performs additional size checks when defined. */ /* Performs additional size checks when defined. */
#undef JEMALLOC_OPT_SIZE_CHECKS #undef JEMALLOC_OPT_SIZE_CHECKS

View File

@@ -1,4 +1,4 @@
#include <mutex> #include <exception>
#include <new> #include <new>
// NOLINTBEGIN(misc-use-anonymous-namespace) // NOLINTBEGIN(misc-use-anonymous-namespace)
@@ -78,29 +78,30 @@ handleOOM(std::size_t size, bool nothrow) {
void *ptr = nullptr; void *ptr = nullptr;
while (ptr == nullptr) { while (ptr == nullptr) {
std::new_handler handler; std::new_handler handler = std::get_new_handler();
// GCC-4.8 and clang 4.0 do not have std::get_new_handler.
{
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
handler = std::set_new_handler(nullptr);
std::set_new_handler(handler);
}
if (handler == nullptr) if (handler == nullptr)
break; break;
#ifdef JEMALLOC_HAVE_CXX_EXCEPTIONS
try { try {
handler(); handler();
} catch (const std::bad_alloc &) { } catch (const std::bad_alloc &) {
break; break;
} }
#else
handler();
#endif
ptr = je_malloc(size); ptr = je_malloc(size);
} }
if (ptr == nullptr && !nothrow) if (ptr == nullptr && !nothrow) {
std::__throw_bad_alloc(); #ifdef JEMALLOC_HAVE_CXX_EXCEPTIONS
throw std::bad_alloc();
#else
std::terminate();
#endif
}
return ptr; return ptr;
} }