diff options
Diffstat (limited to 'lib/common/DebugMemLeakFinder.cpp')
-rw-r--r-- | lib/common/DebugMemLeakFinder.cpp | 98 |
1 files changed, 82 insertions, 16 deletions
diff --git a/lib/common/DebugMemLeakFinder.cpp b/lib/common/DebugMemLeakFinder.cpp index 0b123675..58a82c0e 100644 --- a/lib/common/DebugMemLeakFinder.cpp +++ b/lib/common/DebugMemLeakFinder.cpp @@ -15,14 +15,19 @@ #undef realloc #undef free -#ifdef HAVE_UNISTD_H - #include <unistd.h> -#endif - +#include <limits.h> #include <signal.h> #include <stdio.h> #include <string.h> +#ifdef HAVE_PROCESS_H +# include <process.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + #include <cstdlib> // for std::atexit #include <map> #include <set> @@ -155,7 +160,17 @@ void *memleakfinder_malloc(size_t size, const char *file, int line) InternalAllocGuard guard; void *b = std::malloc(size); - if(!memleakfinder_global_enable) return b; + + if(!memleakfinder_global_enable) + { + // We may not be tracking this allocation, but if + // someone realloc()s the buffer later then it will + // trigger an untracked buffer warning, which we don't + // want to see either. + memleakfinder_notaleak(b); + return b; + } + if(!memleakfinder_initialised) return b; memleakfinder_malloc_add_block(b, size, file, line); @@ -176,25 +191,58 @@ void *memleakfinder_calloc(size_t blocks, size_t size, const char *file, int lin void *memleakfinder_realloc(void *ptr, size_t size) { + if(!ptr) + { + return memleakfinder_malloc(size, "realloc", 0); + } + + if(!size) + { + memleakfinder_free(ptr); + return NULL; + } + InternalAllocGuard guard; + ASSERT(ptr != NULL); + if(!ptr) return NULL; // defensive + if(!memleakfinder_global_enable || !memleakfinder_initialised) { - return std::realloc(ptr, size); + ptr = std::realloc(ptr, size); + if(!memleakfinder_global_enable) + { + // We may not be tracking this allocation, but if + // someone realloc()s the buffer later then it will + // trigger an untracked buffer warning, which we don't + // want to see either. + memleakfinder_notaleak(ptr); + } + return ptr; } // Check it's been allocated std::map<void *, MallocBlockInfo>::iterator i(sMallocBlocks.find(ptr)); - if(ptr && i == sMallocBlocks.end()) + std::set<void *>::iterator j(sNotLeaks.find(ptr)); + + if(i == sMallocBlocks.end() && j == sNotLeaks.end()) { BOX_WARNING("Block " << ptr << " realloc()ated, but not " "in list. Error? Or allocated in startup static " "objects?"); } + if(j != sNotLeaks.end()) + { + // It's in the list of not-leaks, so don't warn about it, + // but it's being reallocated, so remove it from the list too, + // in case it's reassigned, and add the new block below. + sNotLeaks.erase(j); + } + void *b = std::realloc(ptr, size); - if(ptr && i!=sMallocBlocks.end()) + if(i != sMallocBlocks.end()) { // Worked? if(b != 0) @@ -230,10 +278,19 @@ void memleakfinder_free(void *ptr) { // Check it's been allocated std::map<void *, MallocBlockInfo>::iterator i(sMallocBlocks.find(ptr)); + std::set<void *>::iterator j(sNotLeaks.find(ptr)); + if(i != sMallocBlocks.end()) { sMallocBlocks.erase(i); } + else if(j != sNotLeaks.end()) + { + // It's in the list of not-leaks, so don't warn + // about it, but it's being freed, so remove it + // from the list too, in case it's reassigned. + sNotLeaks.erase(j); + } else { BOX_WARNING("Block " << ptr << " freed, but not " @@ -284,7 +341,8 @@ void memleakfinder_notaleak(void *ptr) ASSERT(!sTrackingDataDestroyed); memleakfinder_notaleak_insert_pre(); - if(memleakfinder_global_enable && memleakfinder_initialised) + + if(memleakfinder_initialised) { sNotLeaks.insert(ptr); } @@ -294,7 +352,9 @@ void memleakfinder_notaleak(void *ptr) sizeof(sNotLeaksPre)/sizeof(*sNotLeaksPre) ) sNotLeaksPre[sNotLeaksPreNum++] = ptr; } -/* { + + /* + { std::map<void *, MallocBlockInfo>::iterator i(sMallocBlocks.find(ptr)); if(i != sMallocBlocks.end()) sMallocBlocks.erase(i); } @@ -531,9 +591,14 @@ extern "C" void memleakfinder_atexit() memleakfinder_reportleaks_appendfile(atexit_filename, atexit_markertext); } -void memleakfinder_setup_exit_report(const char *filename, const char *markertext) +void memleakfinder_setup_exit_report(const std::string& filename, + const char *markertext) { - ::strncpy(atexit_filename, filename, sizeof(atexit_filename)-1); + char buffer[PATH_MAX]; + std::string abs_filename = std::string(getcwd(buffer, sizeof(buffer))) + + DIRECTORY_SEPARATOR + filename; + ::strncpy(atexit_filename, abs_filename.c_str(), + sizeof(atexit_filename)-1); ::strncpy(atexit_markertext, markertext, sizeof(atexit_markertext)-1); atexit_filename[sizeof(atexit_filename)-1] = 0; atexit_markertext[sizeof(atexit_markertext)-1] = 0; @@ -544,9 +609,6 @@ void memleakfinder_setup_exit_report(const char *filename, const char *markertex } } - - - void add_object_block(void *block, size_t size, const char *file, int line, bool array) { InternalAllocGuard guard; @@ -557,6 +619,10 @@ void add_object_block(void *block, size_t size, const char *file, int line, bool if(block != 0) { + std::map<void *, ObjectInfo>::iterator j(sObjectBlocks.find(block)); + // The same block should not already be tracked! + ASSERT(j == sObjectBlocks.end()); + ObjectInfo i; i.size = size; i.file = file; @@ -637,7 +703,7 @@ void *operator new(size_t size) } */ -void *operator new[](size_t size) +void *operator new[](size_t size) throw (std::bad_alloc) { return internal_new(size, "standard libraries", 0); } |