Skip to main content
GameDev.net gamedev.net
🔒 Locked

Problem with memory leak detector

Started by MilfredCubicleX Feb 23, 2007 at 2:59 PM 3 replies 2.4k views
Original Post
MilfredCubicleX
MilfredCubicleX
Hey everyone, I'm having some trouble with the memory leak detector described in this tutorial. It usually acts fine for smaller projects, but as this codebase grows, i run into more and more problems. The problem i get is "Unhandled exception at 0x0049706b in HorrorGame.exe: 0xC0000005: Access violation reading location 0x00000004" that points to the code

	_Nodeptr _Ubound(const key_type& _Keyval) const
		{	// find leftmost node greater than _Keyval
>>>>>>>>>>	_Nodeptr _Pnode = _Root();
		_Nodeptr _Wherenode = _Myhead;	// end() if search fails

...


in xtree, which means there's a problem in the stl map that i'm using. I can pinpoint when it happens: destruction of he memory detector class, which is a singleton. I can also know which line I can comment/uncomment to make it work, but I can't figure out why it's happening. Here's the code: MemTracker.h:

#ifndef _MemTracker_h
#define _MemTracker_h

#include <map>
#include <string>

#include <assert.h>

class CMemTracker
{
public:
	static CMemTracker * GetInstance ( );
	static void Destroy ( );

	void AllocNew ( unsigned long address, const char * file, int line );
	void DeleteOld( unsigned long address );

	typedef std::map< unsigned long, std::string >::iterator MemIter;
	std::map< unsigned long, std::string > memAllocs;

private:
	static CMemTracker * _instance;
};

#ifndef _NDEBUG

inline void * __cdecl operator new(unsigned int size, const char *file, int line)
{
	void * ptr = ( void* )malloc( size );
	if( CMemTracker::GetInstance() )
		CMemTracker::GetInstance()->AllocNew( (unsigned long)ptr, file, line );
	return ptr;
};

inline void __cdecl operator delete ( void *p )
{
	if( CMemTracker::GetInstance() )
		CMemTracker::GetInstance()->DeleteOld( (unsigned long)p );
	free( p );
};

inline void * __cdecl operator new[]( unsigned int size, const char *file, int line )
{
	void * ptr = ( void* )malloc( size );
	if( CMemTracker::GetInstance() )
		CMemTracker::GetInstance()->AllocNew( (unsigned long)ptr, file, line );
	return ptr;
};

inline void __cdecl operator delete []( void *p )
{
	if( CMemTracker::GetInstance() )
		CMemTracker::GetInstance()->DeleteOld( (unsigned long)p );
	free( p );
};

#define DEBUG_NEW new(__FILE__, __LINE__)
#else
#define DEBUG_NEW new
#endif


#endif


MemTracker.cpp:

#include "MemTracker.h"

CMemTracker * CMemTracker::_instance;

CMemTracker * CMemTracker::GetInstance ( )
{
	if( !_instance )
	{
		_instance = new CMemTracker ( );
	}
	return _instance;
}

void CMemTracker::Destroy ( )
{
	if( _instance )
	{
		delete _instance;
		_instance = 0;
	}
}

void CMemTracker::AllocNew ( unsigned long address, const char * file, int line )
{
	char temp [ 16 ];
	std::string str;
	str += file;
	str += ": ";
	itoa( line, temp, 10 );
	str += temp;

	memAllocs[ address ] = str;
}

void CMemTracker::DeleteOld( unsigned long address )
{
	memAllocs.erase( address );
}


the line that can be uncommented for the program not to crash is:

	memAllocs.erase( address );
the actual code i stepped into right before i got the error is:

		delete _instance;
I originally thought it was a problem where the class was destructed but DeleteOld was called afterward, but I have a check to make sure the pointer is valid first. Any thoughts?
dmail
dmail
Try stepping through a new call and you will realise its not using your new.

The macro magic missing is
#define new DEBUG_NEW


And then you will get another error due to using a new call in the singleton creator which will call your new call which will check the singleton instance and find it null and then call your new function. See the pattern?
MilfredCubicleX
MilfredCubicleX
Quote:
Original post by dmail
Try stepping through a new call and you will realise its not using your new.

The macro magic missing is
*** Source Snippet Removed ***

And then you will get another error due to using a new call in the singleton creator which will call your new call which will check the singleton instance and find it null and then call your new function. See the pattern?


that macro conflicts with STL so i can't use it, i use DEBUG_NEW for all my allocations, except for the MemTracker allocation because it would be falsely reported as a leak.



*Edit - Whoops, just replacing the delete with a free works. Damn, i hate figuring it out after i post. But your reply did help me think of it, thank you.
jflanglois
jflanglois
Quote:
Original post by MilfredCubicleX
*Edit - Whoops, just replacing the delete with a free works. Damn, i hate figuring it out after i post. But your reply did help me think of it, thank you.


If you used new to allocate your data, then you must use delete to free it. You cannot use delete [] or free(). I believe it's undefined bahavior at best.

[edit] And that tells me that there is probably something wrong in the destructor.


jfl.
MilfredCubicleX
MilfredCubicleX
Quote:
Original post by jflanglois
Quote:
Original post by MilfredCubicleX
*Edit - Whoops, just replacing the delete with a free works. Damn, i hate figuring it out after i post. But your reply did help me think of it, thank you.


If you used new to allocate your data, then you must use delete to free it. You cannot use delete [] or free(). I believe it's undefined bahavior at best.

[edit] And that tells me that there is probably something wrong in the destructor.


jfl.


Whats wrong was that i was using the unoverloaded new for the allocation of MemTracker. i then used delete thinking it would be the unoverloaded version, but instead it erased the pointer to MemTracker, then called the overloaded delete, which tried to access the pointer to MemTracker. Silly mistake on my part.
Thanks for the tip about matching the new.. i'll try to fix that...

I can probably replace = new CMemTracker ( ); with = malloc( sizeof( CMemTracker ) ); right?
I can use the unoverloaded new/delete by doing ::new/::delete right?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.