Skip to content

Commit 0f9729c

Browse files
committed
Check for potential memory leak at runtime rather than on compile time
1 parent b36c55b commit 0f9729c

File tree

3 files changed

+31
-22
lines changed

3 files changed

+31
-22
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ stacktrace_check(BOOST_STACKTRACE_HAS_WINDBG has_windbg.cpp "" "dbgeng;ole32" ""
7272
stacktrace_check(BOOST_STACKTRACE_HAS_WINDBG_CACHED has_windbg_cached.cpp "${CMAKE_CURRENT_SOURCE_DIR}/../config/include" "dbgeng;ole32" "")
7373

7474
set(_default_from_exception ON)
75-
if (NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64|i386|i686|x86" OR CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin")
75+
if (CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin")
7676
set(_default_from_exception OFF)
7777
endif()
7878

build/Jamfile.v2

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,7 @@ rule build-stacktrace-from-exception ( props * )
249249
case "off" : return <build>no ;
250250
}
251251

252-
local arch = [ property.select <architecture> : $(props) ] ;
253-
if ( $(arch) && ( $(arch:G=) != x86 ) ) || ( <target-os>cygwin in $(props) )
252+
if ( <target-os>cygwin in $(props) )
254253
{
255254
configure.log-library-search-result "boost.stacktrace.from_exception" : "no" ;
256255
return <build>no ;

src/from_exception.cpp

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -160,29 +160,13 @@ BOOST_SYMBOL_EXPORT void assert_no_pending_traces() noexcept {
160160
#include <exception>
161161
#include <dlfcn.h>
162162

163+
163164
#if !BOOST_STACKTRACE_ALWAYS_STORE_IN_PADDING
165+
#include <cstdlib>
164166
#include <mutex>
165167
#include <unordered_map>
166168

167-
#ifndef BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK
168-
169-
#ifdef BOOST_HAS_THREADS
170-
171-
#error On this platform memory leaks are possible if capturing stacktrace from \
172-
exceptions is enabled and exceptions are thrown concurrently \
173-
and libc++ runtime is used. \
174-
\
175-
Define `BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK` to \
176-
suppress this error if the library would not be used with libc++ \
177-
runtime (for example, it would be only used with GCC runtime). \
178-
\
179-
Otherwise, disable the boost_stacktrace_from_exception library build \
180-
(for example by `./b2 boost.stacktrace.from_exception=off` option).
181-
182-
#endif
183-
184-
#endif
185-
169+
#include <unistd.h>
186170
#endif
187171

188172
namespace {
@@ -297,6 +281,32 @@ void* __cxa_allocate_exception(size_t thrown_size) throw() {
297281
extern "C" BOOST_SYMBOL_EXPORT
298282
void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
299283
BOOST_ASSERT(is_libcpp_runtime());
284+
285+
#if !defined(BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK) && defined(BOOST_HAS_THREADS)
286+
static const char* leaks_are_fine = std::getenv("BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK");
287+
if (!leaks_are_fine || leaks_are_fine[0] != '1') {
288+
const char* const warning =
289+
"\n\n"
290+
"=======================================================================================\n"
291+
"\n"
292+
"On this platform, memory leaks may occur if capturing stacktrace from exceptions is\n"
293+
"enabled and exceptions are thrown concurrently by libc++ runtime (libc++abi).\n"
294+
"\n"
295+
"A proper workaround is to use libstdc++ runtime (libgcc_s) instead.\n"
296+
"\n"
297+
"Alternatively, if you are willing to accept potential MEMORY LEAKS, set the environment\n"
298+
"variable `BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK=1` to proceed. You can\n"
299+
"also define the `BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK` macro when\n"
300+
"building the `boost_stacktrace_from_exception` library to disable this warning and to\n"
301+
"get the MEMORY LEAKS silently on libc++ runtime.\n"
302+
"\n"
303+
"=======================================================================================\n"
304+
;
305+
write(STDERR_FILENO, warning, strlen(warning));
306+
std::abort();
307+
}
308+
#endif
309+
300310
if (!thrown_object) {
301311
return;
302312
}

0 commit comments

Comments
 (0)