Skip to content

Commit

Permalink
Wrap std::bad_alloc
Browse files Browse the repository at this point in the history
  • Loading branch information
thetic committed Nov 15, 2022
1 parent dc30de2 commit 0f701b9
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 93 deletions.
91 changes: 45 additions & 46 deletions include/CppUTest/CppUTestConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,58 +123,12 @@
#define _check_format_(type, format_parameter, other_parameters) /* type, format_parameter, other_parameters */
#endif

/*
* When we don't link Standard C++, then we won't throw exceptions as we assume the compiler might not support that!
*/

#if CPPUTEST_USE_STD_CPP_LIB
#if defined(__cplusplus) && __cplusplus >= 201103L
#define UT_THROW(exception)
#define UT_NOTHROW noexcept
#else
#define UT_THROW(exception) throw (exception)
#define UT_NOTHROW throw()
#endif
#else
#define UT_THROW(exception)
#ifdef __clang__
#define UT_NOTHROW throw()
#else
#define UT_NOTHROW
#endif
#endif

/*
* Visual C++ doesn't define __cplusplus as C++11 yet (201103), however it doesn't want the throw(exception) either, but
* it does want throw().
*/

#ifdef _MSC_VER
#undef UT_THROW
#define UT_THROW(exception)
#endif

#if defined(__cplusplus) && __cplusplus >= 201103L
#define DEFAULT_COPY_CONSTRUCTOR(classname) classname(const classname &) = default;
#else
#define DEFAULT_COPY_CONSTRUCTOR(classname)
#endif

/*
* g++-4.7 with stdc++11 enabled On MacOSX! will have a different exception specifier for operator new (and thank you!)
* I assume they'll fix this in the future, but for now, we'll change that here.
* (This should perhaps also be done in the configure.ac)
*/

#ifdef __GXX_EXPERIMENTAL_CXX0X__
#ifdef __APPLE__
#ifdef _GLIBCXX_THROW
#undef UT_THROW
#define UT_THROW(exception) _GLIBCXX_THROW(exception)
#endif
#endif
#endif

/*
* Address sanitizer is a good thing... and it causes some conflicts with the CppUTest tests
* To check whether it is on or off, we create a CppUTest define here.
Expand Down Expand Up @@ -270,6 +224,51 @@
#define CPPUTEST_HAVE_EXCEPTIONS 1
#endif
#endif

#if CPPUTEST_HAVE_EXCEPTIONS
#if defined(__cplusplus) && __cplusplus >= 201103L
#define UT_THROW(exception)
#define UT_NOTHROW noexcept
#else
#define UT_THROW(exception) throw (exception)
#define UT_NOTHROW throw()
#endif
#else
#define UT_THROW(exception)
#ifdef __clang__
#define UT_NOTHROW throw()
#else
#define UT_NOTHROW
#endif
#endif

/*
* Visual C++ doesn't define __cplusplus as C++11 yet (201103), however it doesn't want the throw(exception) either, but
* it does want throw().
*/
#ifdef _MSC_VER
#undef UT_THROW
#define UT_THROW(exception)
#endif

/*
* g++-4.7 with stdc++11 enabled On MacOSX! will have a different exception specifier for operator new (and thank you!)
* I assume they'll fix this in the future, but for now, we'll change that here.
* (This should perhaps also be done in the configure.ac)
*/
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
defined(__APPLE__) && \
defined(_GLIBCXX_THROW)
#undef UT_THROW
#define UT_THROW(exception) _GLIBCXX_THROW(exception)
#endif

#if CPPUTEST_USE_STD_CPP_LIB
#define CPPUTEST_BAD_ALLOC std::bad_alloc
#else
class CppUTestBadAlloc {};
#define CPPUTEST_BAD_ALLOC CppUTestBadAlloc
#endif
#endif

/*
Expand Down
12 changes: 6 additions & 6 deletions include/CppUTest/MemoryLeakDetectorNewMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@
* know about all allocations and report freeing of unallocated blocks. Hence, provide both overloads.
*/

void* operator new(size_t size, const char* file, int line) UT_THROW (std::bad_alloc);
void* operator new(size_t size, const char* file, size_t line) UT_THROW (std::bad_alloc);
void* operator new[](size_t size, const char* file, int line) UT_THROW (std::bad_alloc);
void* operator new[](size_t size, const char* file, size_t line) UT_THROW (std::bad_alloc);
void* operator new(size_t size) UT_THROW(std::bad_alloc);
void* operator new[](size_t size) UT_THROW(std::bad_alloc);
void* operator new(size_t size, const char* file, int line) UT_THROW (CPPUTEST_BAD_ALLOC);
void* operator new(size_t size, const char* file, size_t line) UT_THROW (CPPUTEST_BAD_ALLOC);
void* operator new[](size_t size, const char* file, int line) UT_THROW (CPPUTEST_BAD_ALLOC);
void* operator new[](size_t size, const char* file, size_t line) UT_THROW (CPPUTEST_BAD_ALLOC);
void* operator new(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC);
void* operator new[](size_t size) UT_THROW(CPPUTEST_BAD_ALLOC);

void operator delete(void* mem, const char* file, int line) UT_NOTHROW;
void operator delete(void* mem, const char* file, size_t line) UT_NOTHROW;
Expand Down
60 changes: 29 additions & 31 deletions src/CppUTest/MemoryLeakWarningPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,13 @@ void cpputest_free_location_with_leak_detection(void* buffer, const char* file,
#if CPPUTEST_USE_MEM_LEAK_DETECTION
#undef new

#if !CPPUTEST_HAVE_EXCEPTIONS
#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory)
#elif CPPUTEST_USE_STD_CPP_LIB
#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory) if (memory == NULLPTR) throw std::bad_alloc()
#if CPPUTEST_HAVE_EXCEPTIONS
#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory) if (memory == NULLPTR) throw CPPUTEST_BAD_ALLOC()
#else
#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory) if (memory == NULLPTR) throw 7
#define UT_THROW_BAD_ALLOC_WHEN_NULL(memory)
#endif

static void* threadsafe_mem_leak_operator_new (size_t size) UT_THROW(std::bad_alloc)
static void* threadsafe_mem_leak_operator_new (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
MemLeakScopedMutex lock;
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
Expand All @@ -152,15 +150,15 @@ static void* threadsafe_mem_leak_operator_new_nothrow (size_t size) UT_NOTHROW
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
}

static void* threadsafe_mem_leak_operator_new_debug (size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc)
static void* threadsafe_mem_leak_operator_new_debug (size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
MemLeakScopedMutex lock;
void *memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size, file, line);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
return memory;
}

static void* threadsafe_mem_leak_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
static void* threadsafe_mem_leak_operator_new_array (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
MemLeakScopedMutex lock;
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
Expand All @@ -174,7 +172,7 @@ static void* threadsafe_mem_leak_operator_new_array_nothrow (size_t size) UT_NOT
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
}

static void* threadsafe_mem_leak_operator_new_array_debug (size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc)
static void* threadsafe_mem_leak_operator_new_array_debug (size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
MemLeakScopedMutex lock;
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size, file, line);
Expand All @@ -197,7 +195,7 @@ static void threadsafe_mem_leak_operator_delete_array (void* mem) UT_NOTHROW
}


static void* mem_leak_operator_new (size_t size) UT_THROW(std::bad_alloc)
static void* mem_leak_operator_new (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
Expand All @@ -209,14 +207,14 @@ static void* mem_leak_operator_new_nothrow (size_t size) UT_NOTHROW
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size);
}

static void* mem_leak_operator_new_debug (size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc)
static void* mem_leak_operator_new_debug (size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void *memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewAllocator(), size, file, line);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
return memory;
}

static void* mem_leak_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
static void* mem_leak_operator_new_array (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
Expand All @@ -228,7 +226,7 @@ static void* mem_leak_operator_new_array_nothrow (size_t size) UT_NOTHROW
return MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size);
}

static void* mem_leak_operator_new_array_debug (size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc)
static void* mem_leak_operator_new_array_debug (size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(getCurrentNewArrayAllocator(), size, file, line);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
Expand All @@ -247,7 +245,7 @@ static void mem_leak_operator_delete_array (void* mem) UT_NOTHROW
MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(getCurrentNewArrayAllocator(), (char*) mem);
}

static void* normal_operator_new (size_t size) UT_THROW(std::bad_alloc)
static void* normal_operator_new (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = PlatformSpecificMalloc(size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
Expand All @@ -259,14 +257,14 @@ static void* normal_operator_new_nothrow (size_t size) UT_NOTHROW
return PlatformSpecificMalloc(size);
}

static void* normal_operator_new_debug (size_t size, const char* /*file*/, size_t /*line*/) UT_THROW(std::bad_alloc)
static void* normal_operator_new_debug (size_t size, const char* /*file*/, size_t /*line*/) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = PlatformSpecificMalloc(size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
return memory;
}

static void* normal_operator_new_array (size_t size) UT_THROW(std::bad_alloc)
static void* normal_operator_new_array (size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = PlatformSpecificMalloc(size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
Expand All @@ -278,7 +276,7 @@ static void* normal_operator_new_array_nothrow (size_t size) UT_NOTHROW
return PlatformSpecificMalloc(size);
}

static void* normal_operator_new_array_debug (size_t size, const char* /*file*/, size_t /*line*/) UT_THROW(std::bad_alloc)
static void* normal_operator_new_array_debug (size_t size, const char* /*file*/, size_t /*line*/) UT_THROW(CPPUTEST_BAD_ALLOC)
{
void* memory = PlatformSpecificMalloc(size);
UT_THROW_BAD_ALLOC_WHEN_NULL(memory);
Expand All @@ -295,36 +293,36 @@ static void normal_operator_delete_array (void* mem) UT_NOTHROW
PlatformSpecificFree(mem);
}

static void *(*operator_new_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new;
static void *(*operator_new_fptr)(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new;
static void *(*operator_new_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_nothrow;
static void *(*operator_new_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_debug;
static void *(*operator_new_array_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array;
static void *(*operator_new_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_debug;
static void *(*operator_new_array_fptr)(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_array;
static void *(*operator_new_array_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_array_nothrow;
static void *(*operator_new_array_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array_debug;
static void *(*operator_new_array_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_array_debug;
static void (*operator_delete_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete;
static void (*operator_delete_array_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete_array;

static void *(*saved_operator_new_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new;
static void *(*saved_operator_new_fptr)(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new;
static void *(*saved_operator_new_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_nothrow;
static void *(*saved_operator_new_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_debug;
static void *(*saved_operator_new_array_fptr)(size_t size) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array;
static void *(*saved_operator_new_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_debug;
static void *(*saved_operator_new_array_fptr)(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_array;
static void *(*saved_operator_new_array_nothrow_fptr)(size_t size) UT_NOTHROW = mem_leak_operator_new_array_nothrow;
static void *(*saved_operator_new_array_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc) = mem_leak_operator_new_array_debug;
static void *(*saved_operator_new_array_debug_fptr)(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC) = mem_leak_operator_new_array_debug;
static void (*saved_operator_delete_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete;
static void (*saved_operator_delete_array_fptr)(void* mem) UT_NOTHROW = mem_leak_operator_delete_array;
static int save_counter = 0;

void* operator new(size_t size) UT_THROW(std::bad_alloc)
void* operator new(size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_fptr(size);
}

void* operator new(size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
void* operator new(size_t size, const char* file, int line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_debug_fptr(size, file, (size_t)line);
}

void* operator new(size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc)
void* operator new(size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_debug_fptr(size, file, line);
}
Expand All @@ -351,17 +349,17 @@ void operator delete (void* mem, size_t) UT_NOTHROW
}
#endif

void* operator new[](size_t size) UT_THROW(std::bad_alloc)
void* operator new[](size_t size) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_array_fptr(size);
}

void* operator new [](size_t size, const char* file, int line) UT_THROW(std::bad_alloc)
void* operator new [](size_t size, const char* file, int line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_array_debug_fptr(size, file, (size_t)line);
}

void* operator new [](size_t size, const char* file, size_t line) UT_THROW(std::bad_alloc)
void* operator new [](size_t size, const char* file, size_t line) UT_THROW(CPPUTEST_BAD_ALLOC)
{
return operator_new_array_debug_fptr(size, file, line);
}
Expand Down
14 changes: 4 additions & 10 deletions tests/CppUTest/MemoryOperatorOverloadTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,20 +421,14 @@ TEST_GROUP(OutOfMemoryTestsForOperatorNew)

#if CPPUTEST_HAVE_EXCEPTIONS

#if CPPUTEST_USE_STD_CPP_LIB
#define BAD_ALLOC std::bad_alloc
#else
#define BAD_ALLOC int
#endif

TEST(OutOfMemoryTestsForOperatorNew, FailingNewOperatorThrowsAnExceptionWhenUsingStdCppNew)
{
CHECK_THROWS(BAD_ALLOC, new char);
CHECK_THROWS(CPPUTEST_BAD_ALLOC, new char);
}

TEST(OutOfMemoryTestsForOperatorNew, FailingNewArrayOperatorThrowsAnExceptionWhenUsingStdCppNew)
{
CHECK_THROWS(BAD_ALLOC, new char[10]);
CHECK_THROWS(CPPUTEST_BAD_ALLOC, new char[10]);
}

TEST_GROUP(TestForExceptionsInConstructor)
Expand Down Expand Up @@ -506,12 +500,12 @@ char* some_memory;

TEST(OutOfMemoryTestsForOperatorNew, FailingNewOperatorThrowsAnExceptionWhenUsingStdCppNewWithoutOverride)
{
CHECK_THROWS(BAD_ALLOC, some_memory = new char);
CHECK_THROWS(CPPUTEST_BAD_ALLOC, some_memory = new char);
}

TEST(OutOfMemoryTestsForOperatorNew, FailingNewArrayOperatorThrowsAnExceptionWhenUsingStdCppNewWithoutOverride)
{
CHECK_THROWS(BAD_ALLOC, some_memory = new char[10]);
CHECK_THROWS(CPPUTEST_BAD_ALLOC, some_memory = new char[10]);
}

#if CPPUTEST_USE_STD_CPP_LIB
Expand Down

0 comments on commit 0f701b9

Please sign in to comment.