[Box Backup-commit] COMMIT r1314 - box/chris/general/lib/common

boxbackup-dev at fluffy.co.uk boxbackup-dev at fluffy.co.uk
Sat Mar 3 21:40:15 GMT 2007


Author: chris
Date: 2007-03-03 21:40:15 +0000 (Sat, 03 Mar 2007)
New Revision: 1314

Modified:
   box/chris/general/lib/common/DebugMemLeakFinder.cpp
   box/chris/general/lib/common/MemLeakFinder.h
Log:
Improve leak finder to track some leaks in allocations by standard libs.

Added memleakfinder_init() which must be called in main().

Added a MemLeakSuppressionGuard class to suppress leaks in test code.

(from chris/merge)


Modified: box/chris/general/lib/common/DebugMemLeakFinder.cpp
===================================================================
--- box/chris/general/lib/common/DebugMemLeakFinder.cpp	2007-03-03 21:36:16 UTC (rev 1313)
+++ box/chris/general/lib/common/DebugMemLeakFinder.cpp	2007-03-03 21:40:15 UTC (rev 1314)
@@ -25,6 +25,9 @@
 #include <string.h>
 #include <set>
 
+#include "MemLeakFinder.h"
+
+static bool memleakfinder_initialised = false;
 bool memleakfinder_global_enable = false;
 
 typedef struct
@@ -55,11 +58,41 @@
 	static std::set<void *> sNotLeaks;
 
 	void *sNotLeaksPre[1024];
-	int sNotLeaksPreNum = 0;
+	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 +108,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 +124,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 +170,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 +182,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,31 +199,41 @@
 
 void memleakfinder_notaleak_insert_pre()
 {
+	InternalAllocGuard guard;
+
 	if(!memleakfinder_global_enable) return;
-	for(int l = 0; l < sNotLeaksPreNum; l++)
+	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);
 	}
 	else
 	{
 		if ( sNotLeaksPreNum < 
-			 (unsigned)( sizeof(sNotLeaksPre)/sizeof(*sNotLeaksPre) ) )
+			 sizeof(sNotLeaksPre)/sizeof(*sNotLeaksPre) )
 			sNotLeaksPre[sNotLeaksPreNum++] = ptr;
 	}
 /*	{
@@ -206,6 +255,9 @@
 // start monitoring a section of code
 void memleakfinder_startsectionmonitor()
 {
+	InternalAllocGuard guard;
+
+	ASSERT(memleakfinder_initialised);
 	sTrackMallocInSection = true;
 	sSectionMallocBlocks.clear();
 	sTrackObjectsInSection = true;
@@ -215,6 +267,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 +281,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 +305,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,24 +314,30 @@
 
 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%08p size %d allocated at %s:%d\n", i->first, i->second.size, i->second.file, i->second.line);
+		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);
 	}
 	for(std::map<void *, ObjectInfo>::const_iterator i(sObjectBlocks.begin()); i != sObjectBlocks.end(); ++i)
 	{
-		if(is_leak(i->first)) ::fprintf(file, "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);
+		if(is_leak(i->first)) ::fprintf(file, "Object%s 0x%p size %d allocated at %s:%d\n", i->second.array?" []":"", i->first, i->second.size, i->second.file, i->second.line);
 	}
 }
 
 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 +384,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 +407,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 +430,68 @@
 	// 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
+// disabled because it causes hangs on FC2 in futex() in test/common
+// while reading files. reason unknown.
+/*
+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/general/lib/common/MemLeakFinder.h
===================================================================
--- box/chris/general/lib/common/MemLeakFinder.h	2007-03-03 21:36:16 UTC (rev 1313)
+++ box/chris/general/lib/common/MemLeakFinder.h	2007-03-03 21:40:15 UTC (rev 1314)
@@ -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,12 +50,9 @@
 
 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 delete(void *ptr) throw ();
-void operator delete[](void *ptr) throw ();
-
 // define the malloc functions now, if required
 #ifdef MEMLEAKFINDER_FULL_MALLOC_MONITORING
 	#define malloc(X)	memleakfinder_malloc(X, __FILE__, __LINE__)
@@ -55,6 +61,5 @@
 	#define MEMLEAKFINDER_MALLOC_MONITORING_DEFINED
 #endif
 
-
 #endif // MEMLEAKFINDER__H
 




More information about the Boxbackup-commit mailing list