diff options
author | Tavian Barnes <tavianator@gmail.com> | 2011-05-16 23:44:06 -0600 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2011-05-16 23:44:06 -0600 |
commit | a932d4f46c2fadd6c750d844846fb9ba4baf45e0 (patch) | |
tree | 6f459c60433752713a74f84c8dddd1004037c91d /libdimension | |
parent | d374841194f24c7cb1cdc52fc631fcb2982af358 (diff) | |
download | dimension-a932d4f46c2fadd6c750d844846fb9ba4baf45e0.tar.xz |
Add basic leak check.
Diffstat (limited to 'libdimension')
-rw-r--r-- | libdimension/compiler.h | 8 | ||||
-rw-r--r-- | libdimension/malloc.c | 33 | ||||
-rw-r--r-- | libdimension/profile.c | 2 | ||||
-rw-r--r-- | libdimension/prtree.c | 2 |
4 files changed, 40 insertions, 5 deletions
diff --git a/libdimension/compiler.h b/libdimension/compiler.h index cb77ca6..d6435d0 100644 --- a/libdimension/compiler.h +++ b/libdimension/compiler.h @@ -39,9 +39,13 @@ #endif #ifdef __GNUC__ - #define DMNSN_HOT __attribute__((hot)) - #define DMNSN_INTERNAL __attribute__((visibility("hidden"))) + #define DMNSN_HOT __attribute__((hot)) + #define DMNSN_INTERNAL __attribute__((visibility("hidden"))) + #define DMNSN_DESTRUCTOR __attribute__((destructor(102))) + #define DMNSN_LATE_DESTRUCTOR __attribute__((destructor(101))) #else #define DMNSN_HOT #define DMNSN_INTERNAL + #define DMNSN_DESTRUCTOR + #define DMNSN_LATE_DESTRUCTOR #endif diff --git a/libdimension/malloc.c b/libdimension/malloc.c index 91364d4..2f11281 100644 --- a/libdimension/malloc.c +++ b/libdimension/malloc.c @@ -23,10 +23,14 @@ * Dynamic memory. */ -#include "dimension.h" +#include "dimension-impl.h" #include <stdlib.h> #include <string.h> +#ifndef NDEBUG +static size_t dmnsn_allocs = 0; +#endif + void * dmnsn_malloc(size_t size) { @@ -34,12 +38,23 @@ dmnsn_malloc(size_t size) if (!ptr) { dmnsn_error("Memory allocation failed."); } + +#ifndef NDEBUG + __sync_fetch_and_add(&dmnsn_allocs, 1); +#endif + return ptr; } void * dmnsn_realloc(void *ptr, size_t size) { +#ifndef NDEBUG + if (!ptr) { + __sync_fetch_and_add(&dmnsn_allocs, 1); + } +#endif + ptr = realloc(ptr, size); if (!ptr) { dmnsn_error("Memory allocation failed."); @@ -58,5 +73,21 @@ dmnsn_strdup(const char *s) void dmnsn_free(void *ptr) { +#ifndef NDEBUG + if (ptr) { + __sync_fetch_and_sub(&dmnsn_allocs, 1); + } +#endif + free(ptr); } + +#ifndef NDEBUG +DMNSN_LATE_DESTRUCTOR static void +dmnsn_leak_check(void) +{ + if (dmnsn_allocs > 0) { + dmnsn_warning("Leaking memory."); + } +} +#endif diff --git a/libdimension/profile.c b/libdimension/profile.c index f9dd2d9..8fca36a 100644 --- a/libdimension/profile.c +++ b/libdimension/profile.c @@ -169,7 +169,7 @@ dmnsn_print_bad_prediction(void *ptr) dmnsn_free(branch->location); } -static void __attribute__((destructor)) +DMNSN_DESTRUCTOR static void dmnsn_print_bad_predictions(void) { dmnsn_dictionary *thread_profile = dmnsn_get_thread_profile(); diff --git a/libdimension/prtree.c b/libdimension/prtree.c index e73ea16..2d8acc4 100644 --- a/libdimension/prtree.c +++ b/libdimension/prtree.c @@ -564,7 +564,7 @@ dmnsn_get_prtree_caches(void) /** Needed because pthreads doesn't destroy data from the main thread unless it exits with pthread_exit(). */ -static void __attribute__((destructor)) +DMNSN_DESTRUCTOR static void dmnsn_delete_main_prtree_caches(void) { dmnsn_delete_array(dmnsn_get_prtree_caches()); |