diff --git a/CMakeLists.txt b/CMakeLists.txt index eee63198e..8df6f9527 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ option(HAVE_ASSERT_LOG "assert_log enabled by default" ON) option(HAVE_ASSERT_PANIC "assert_panic disabled by default" OFF) option(HAVE_LOGGING "logging enabled by default" ON) option(HAVE_STATS "stats enabled by default" ON) +option(HAVE_DEBUG_MM "debugging oriented memory management disabled by default" OFF) option(COVERAGE "code coverage" OFF) include(CheckIncludeFiles) diff --git a/config.h.in b/config.h.in index e5fa50e30..f1dc18bd9 100644 --- a/config.h.in +++ b/config.h.in @@ -17,3 +17,5 @@ #cmakedefine HAVE_LOGGING #cmakedefine HAVE_STATS + +#cmakedefine HAVE_DEBUG_MM diff --git a/include/cc_define.h b/include/cc_define.h index b542d0201..b521b133e 100644 --- a/include/cc_define.h +++ b/include/cc_define.h @@ -54,10 +54,9 @@ extern "C" { # define CC_BACKTRACE 1 #endif -/* TODO: add compile time option to turn chaining on/off */ -/*#ifdef HAVE_CHAINED*/ -# define CC_HAVE_CHAINED 1 -/*#endif*/ +#ifdef HAVE_DEBUG_MM +#define CC_DEBUG_MM 1 +#endif #define CC_OK 0 #define CC_ERROR -1 diff --git a/include/cc_mm.h b/include/cc_mm.h index a1cc574b3..9705bd840 100644 --- a/include/cc_mm.h +++ b/include/cc_mm.h @@ -17,6 +17,8 @@ #pragma once +#include + #include /* @@ -41,8 +43,13 @@ #define cc_calloc(_n, _s) \ _cc_calloc((size_t)(_n), (size_t)(_s), __FILE__, __LINE__) +#if defined CC_DEBUG_MM && CC_DEBUG_MM == 1 +#define cc_realloc(_p, _s) \ + _cc_realloc_move(_p, (size_t)(_s), __FILE__, __LINE__) +#else #define cc_realloc(_p, _s) \ _cc_realloc(_p, (size_t)(_s), __FILE__, __LINE__) +#endif #define cc_free(_p) do { \ _cc_free(_p, __FILE__, __LINE__); \ @@ -59,6 +66,7 @@ void * _cc_alloc(size_t size, const char *name, int line); void * _cc_zalloc(size_t size, const char *name, int line); void * _cc_calloc(size_t nmemb, size_t size, const char *name, int line); void * _cc_realloc(void *ptr, size_t size, const char *name, int line); +void * _cc_realloc_move(void *ptr, size_t size, const char *name, int line); void _cc_free(void *ptr, const char *name, int line); void * _cc_mmap(size_t size, const char *name, int line); int _cc_munmap(void *p, size_t size, const char *name, int line); diff --git a/src/cc_mm.c b/src/cc_mm.c index 4668d8d8e..6a0554289 100644 --- a/src/cc_mm.c +++ b/src/cc_mm.c @@ -34,7 +34,10 @@ _cc_alloc(size_t size, const char *name, int line) { void *p; - ASSERT(size != 0); + if (size == 0) { + log_debug("malloc(0) @ %s:%d", name, line); + return NULL; + } p = malloc(size); if (p == NULL) { @@ -70,7 +73,11 @@ _cc_realloc(void *ptr, size_t size, const char *name, int line) { void *p; - ASSERT(size != 0); + if (size == 0) { + free(ptr); + log_debug("realloc(0) @ %s:%d", name, line); + return NULL; + } p = realloc(ptr, size); if (p == NULL) { @@ -82,10 +89,37 @@ _cc_realloc(void *ptr, size_t size, const char *name, int line) return p; } +void * +_cc_realloc_move(void *ptr, size_t size, const char *name, int line) +{ + void *p = NULL, *pr; + + if (size == 0) { + free(ptr); + log_debug("realloc(0) @ %s:%d", name, line); + return NULL; + } + + /* + * Calling realloc then malloc allows us to force this function call to + * change the address of the allocated memory block. realloc ensures we can + * copy size bytes, and calling malloc before the realloc'd data is free'd + * gives us a new address for the memory object. + */ + if (((pr = realloc(ptr, size)) == NULL || (p = malloc(size)) == NULL)) { + log_error("realloc(%zu) failed @ %s:%d", size, name, line); + } else { + log_vverb("realloc(%zu) at %p @ %s:%d", size, p, name, line); + memcpy(p, pr, size); + } + + free(pr); + return p; +} + void _cc_free(void *ptr, const char *name, int line) { - ASSERT(ptr != NULL); log_vverb("free(%p) @ %s:%d", ptr, name, line); free(ptr); } @@ -103,10 +137,10 @@ _cc_mmap(size_t size, const char *name, int line) * is set appropriately. */ p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, - -1, 0); + -1, 0); if (p == ((void *) -1)) { log_error("mmap %zu bytes @ %s:%d failed: %s", size, name, line, - strerror(errno)); + strerror(errno)); return NULL; } @@ -128,7 +162,7 @@ _cc_munmap(void *p, size_t size, const char *name, int line) status = munmap(p, size); if (status < 0) { log_error("munmap %p @ %s:%d failed: %s", p, name, line, - strerror(errno)); + strerror(errno)); } return status;