summaryrefslogtreecommitdiff
path: root/lib/common/DebugMemLeakFinder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common/DebugMemLeakFinder.cpp')
-rw-r--r--lib/common/DebugMemLeakFinder.cpp98
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);
}