[Box Backup-commit] COMMIT r1159 - box/chris/merge/lib/common

boxbackup-dev at fluffy.co.uk boxbackup-dev at fluffy.co.uk
Mon Nov 13 16:07:36 GMT 2006


Author: chris
Date: 2006-11-13 16:07:36 +0000 (Mon, 13 Nov 2006)
New Revision: 1159

Modified:
   box/chris/merge/lib/common/DebugMemLeakFinder.cpp
   box/chris/merge/lib/common/MemLeakFinder.h
Log:
 * Track memory leaks in allocations via the standard libraries, and 
   avoid malloc/delete mismatches, by overriding standard new operator.
 * Added another global enable flag to memleak finder, which is used to 
   mark the end of static allocations and the start of dynamic code, 
   since the memory leak detection is done before cleanup of static 
   objects.
 * Added a public guard class, to allow safe scoped disabling of memory 
   leak detection.
 * Added InternalAllocGuard to protect against recursive loops when 
   allocating memory inside the memory leak checker. (refs #3)


Modified: box/chris/merge/lib/common/DebugMemLeakFinder.cpp
===================================================================
--- box/chris/merge/lib/common/DebugMemLeakFinder.cpp	2006-11-13 16:00:52 UTC (rev 1158)
+++ box/chris/merge/lib/common/DebugMemLeakFinder.cpp	2006-11-13 16:07:36 UTC (rev 1159)
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <set>
 
+static bool memleakfinder_initialised = false;
 bool memleakfinder_global_enable = false;
 
 typedef struct
@@ -58,8 +59,38 @@
 	size_t sNotLeaksPreNum = 0;
 }
 
+void memleakfinder_init()
+{
+	ASSERT(!memleakfinder_initialised);
+	memleakfinder_initialised = true;
+}
+
+MemLeakSuppressionGuard::MemLeakSuppressionGuard()
+{
+	ASSERT(memleakfinder_global_enable);
+	memleakfinder_global_enable = false;
+}
+
+MemLeakSuppressionGuard::~MemLeakSuppressionGuard()
+{
+	ASSERT(!memleakfinder_global_enable);
+	memleakfinder_global_enable = true;
+}
+
+// these functions may well allocate memory, which we don't want to track.
+static int sInternalAllocDepth = 0;
+
+class InternalAllocGuard
+{
+	public:
+	InternalAllocGuard () { sInternalAllocDepth++; }
+	~InternalAllocGuard() { sInternalAllocDepth--; }
+};
+
 void memleakfinder_malloc_add_block(void *b, size_t size, const char *file, int line)
 {
+	InternalAllocGuard guard;
+
 	if(b != 0)
 	{
 		MallocBlockInfo i;
@@ -75,11 +106,13 @@
 	}
 }
 
-
 void *memleakfinder_malloc(size_t size, const char *file, int line)
 {
+	InternalAllocGuard guard;
+
 	void *b = ::malloc(size);
 	if(!memleakfinder_global_enable) return b;
+	if(!memleakfinder_initialised)   return b;
 
 	memleakfinder_malloc_add_block(b, size, file, line);
 
@@ -89,7 +122,9 @@
 
 void *memleakfinder_realloc(void *ptr, size_t size)
 {
-	if(!memleakfinder_global_enable)
+	InternalAllocGuard guard;
+
+	if(!memleakfinder_global_enable || !memleakfinder_initialised)
 	{
 		return ::realloc(ptr, size);
 	}
@@ -133,7 +168,9 @@
 
 void memleakfinder_free(void *ptr)
 {
-	if(memleakfinder_global_enable)
+	InternalAllocGuard guard;
+
+	if(memleakfinder_global_enable && memleakfinder_initialised)
 	{
 		// Check it's been allocated
 		std::map<void *, MallocBlockInfo>::iterator i(sMallocBlocks.find(ptr));
@@ -143,7 +180,7 @@
 		}
 		else
 		{
-			TRACE1("Block %x freed, but not known. Error? Or allocated in startup static allocation?\n", ptr);
+			TRACE1("Block %p freed, but not known. Error? Or allocated in startup static allocation?\n", ptr);
 		}
 
 		if(sTrackMallocInSection)
@@ -160,24 +197,34 @@
 
 void memleakfinder_notaleak_insert_pre()
 {
+	InternalAllocGuard guard;
+
 	if(!memleakfinder_global_enable) return;
+	if(!memleakfinder_initialised)   return;
+
 	for(size_t l = 0; l < sNotLeaksPreNum; l++)
 	{
 		sNotLeaks.insert(sNotLeaksPre[l]);
 	}
+
 	sNotLeaksPreNum = 0;
 }
 
 bool is_leak(void *ptr)
 {
+	InternalAllocGuard guard;
+
+	ASSERT(memleakfinder_initialised);
 	memleakfinder_notaleak_insert_pre();
 	return sNotLeaks.find(ptr) == sNotLeaks.end();
 }
 
 void memleakfinder_notaleak(void *ptr)
 {
+	InternalAllocGuard guard;
+
 	memleakfinder_notaleak_insert_pre();
-	if(memleakfinder_global_enable)
+	if(memleakfinder_global_enable && memleakfinder_initialised)
 	{
 		sNotLeaks.insert(ptr);
 	}
@@ -206,6 +253,9 @@
 // start monitoring a section of code
 void memleakfinder_startsectionmonitor()
 {
+	InternalAllocGuard guard;
+
+	ASSERT(memleakfinder_initialised);
 	sTrackMallocInSection = true;
 	sSectionMallocBlocks.clear();
 	sTrackObjectsInSection = true;
@@ -215,6 +265,10 @@
 // trace all blocks allocated and still allocated since memleakfinder_startsectionmonitor() called
 void memleakfinder_traceblocksinsection()
 {
+	InternalAllocGuard guard;
+
+	ASSERT(memleakfinder_initialised);
+
 	std::set<void *>::iterator s(sSectionMallocBlocks.begin());
 	for(; s != sSectionMallocBlocks.end(); ++s)
 	{
@@ -225,17 +279,21 @@
 		}
 		else
 		{
-			TRACE4("Block 0x%08p size %d allocated at %s:%d\n", i->first, i->second.size, i->second.file, i->second.line);
+			TRACE4("Block %p size %d allocated at %s:%d\n", i->first, i->second.size, i->second.file, i->second.line);
 		}
 	}
 	for(std::map<void *, ObjectInfo>::const_iterator i(sSectionObjectBlocks.begin()); i != sSectionObjectBlocks.end(); ++i)
 	{
-		TRACE5("Object%s 0x%08p size %d allocated at %s:%d\n", i->second.array?" []":"", i->first, i->second.size, i->second.file, i->second.line);
+		TRACE5("Object%s %p size %d allocated at %s:%d\n", i->second.array?" []":"", i->first, i->second.size, i->second.file, i->second.line);
 	}
 }
 
 int memleakfinder_numleaks()
 {
+	InternalAllocGuard guard;
+
+	ASSERT(memleakfinder_initialised);
+
 	int n = 0;
 	
 	for(std::map<void *, MallocBlockInfo>::const_iterator i(sMallocBlocks.begin()); i != sMallocBlocks.end(); ++i)
@@ -245,6 +303,7 @@
 	
 	for(std::map<void *, ObjectInfo>::const_iterator i(sObjectBlocks.begin()); i != sObjectBlocks.end(); ++i)
 	{
+		const ObjectInfo& rInfo = i->second;
 		if(is_leak(i->first)) ++n;
 	}
 
@@ -253,6 +312,8 @@
 
 void memleakfinder_reportleaks_file(FILE *file)
 {
+	InternalAllocGuard guard;
+
 	for(std::map<void *, MallocBlockInfo>::const_iterator i(sMallocBlocks.begin()); i != sMallocBlocks.end(); ++i)
 	{
 		if(is_leak(i->first)) ::fprintf(file, "Block 0x%p size %d allocated at %s:%d\n", i->first, i->second.size, i->second.file, i->second.line);
@@ -265,12 +326,16 @@
 
 void memleakfinder_reportleaks()
 {
+	InternalAllocGuard guard;
+
 	// report to stdout
 	memleakfinder_reportleaks_file(stdout);
 }
 
 void memleakfinder_reportleaks_appendfile(const char *filename, const char *markertext)
 {
+	InternalAllocGuard guard;
+
 	FILE *file = ::fopen(filename, "a");
 	if(file != 0)
 	{
@@ -317,7 +382,10 @@
 
 void add_object_block(void *block, size_t size, const char *file, int line, bool array)
 {
+	InternalAllocGuard guard;
+
 	if(!memleakfinder_global_enable) return;
+	if(!memleakfinder_initialised)   return;
 
 	if(block != 0)
 	{
@@ -337,7 +405,10 @@
 
 void remove_object_block(void *block)
 {
+	InternalAllocGuard guard;
+
 	if(!memleakfinder_global_enable) return;
+	if(!memleakfinder_initialised)   return;
 
 	std::map<void *, ObjectInfo>::iterator i(sObjectBlocks.find(block));
 	if(i != sObjectBlocks.end())
@@ -357,34 +428,64 @@
 	// If it's not in the list, just ignore it, as lots of stuff goes this way...
 }
 
-void *operator new(size_t size, const char *file, int line)
+static void *internal_new(size_t size, const char *file, int line)
 {
-	void *r = ::malloc(size);
-	add_object_block(r, size, file, line, false);
-	//TRACE4("new(), %d, %s, %d, %08x\n", size, file, line, r);
+	void *r;
+
+	{
+		InternalAllocGuard guard;
+		r = ::malloc(size);
+	}
+	
+	if (sInternalAllocDepth == 0)
+	{
+		InternalAllocGuard guard;
+		add_object_block(r, size, file, line, false);
+		//TRACE4("new(), %d, %s, %d, %08x\n", size, file, line, r);
+	}
+
 	return r;
 }
 
+void *operator new(size_t size, const char *file, int line)
+{
+	return internal_new(size, file, line);
+}
+
 void *operator new[](size_t size, const char *file, int line)
 {
-	void *r = ::malloc(size);
-	add_object_block(r, size, file, line, true);
-	//TRACE4("new[](), %d, %s, %d, %08x\n", size, file, line, r);
-	return r;
+	return internal_new(size, file, line);
 }
 
-void operator delete[](void *ptr) throw ()
+// where there is no doctor... need to override standard new() too
+// http://www.relisoft.com/book/tech/9new.html
+void *operator new(size_t size)
 {
+	return internal_new(size, "standard libraries", 0);
+}
+
+void *operator new[](size_t size)
+{
+	return internal_new(size, "standard libraries", 0);
+}
+
+void internal_delete(void *ptr)
+{
+	InternalAllocGuard guard;
+
 	::free(ptr);
 	remove_object_block(ptr);
 	//TRACE1("delete[]() called, %08x\n", ptr);
 }
 
+void operator delete[](void *ptr) throw ()
+{
+	internal_delete(ptr);
+}
+
 void operator delete(void *ptr) throw ()
 {
-	::free(ptr);
-	remove_object_block(ptr);
-	//TRACE1("delete() called, %08x\n", ptr);
+	internal_delete(ptr);
 }
 
 #endif // NDEBUG

Modified: box/chris/merge/lib/common/MemLeakFinder.h
===================================================================
--- box/chris/merge/lib/common/MemLeakFinder.h	2006-11-13 16:00:52 UTC (rev 1158)
+++ box/chris/merge/lib/common/MemLeakFinder.h	2006-11-13 16:07:36 UTC (rev 1159)
@@ -20,6 +20,13 @@
 // global enable flag
 extern bool memleakfinder_global_enable;
 
+class MemLeakSuppressionGuard
+{
+	public:
+	MemLeakSuppressionGuard();
+	~MemLeakSuppressionGuard();
+};
+
 extern "C"
 {
 	void *memleakfinder_malloc(size_t size, const char *file, int line);
@@ -27,6 +34,8 @@
 	void memleakfinder_free(void *ptr);
 }
 
+void memleakfinder_init();
+
 int memleakfinder_numleaks();
 
 void memleakfinder_reportleaks();
@@ -41,10 +50,12 @@
 
 void memleakfinder_notaleak(void *ptr);
 
-void *operator new(size_t size, const char *file, int line);
+void *operator new  (size_t size, const char *file, int line);
 void *operator new[](size_t size, const char *file, int line);
+void *operator new  (size_t size);
+void *operator new[](size_t size);
 
-void operator delete(void *ptr) throw ();
+void operator delete  (void *ptr) throw ();
 void operator delete[](void *ptr) throw ();
 
 // define the malloc functions now, if required
@@ -55,6 +66,5 @@
 	#define MEMLEAKFINDER_MALLOC_MONITORING_DEFINED
 #endif
 
-
 #endif // MEMLEAKFINDER__H
 




More information about the Boxbackup-commit mailing list