Listing 2: Implements class HandleTracker
#ifdef _DEBUG
#include <afx.h>
// ********************
// HandleTracker class:
// ********************
class HandleTracker
{
public:
HandleTracker();
~HandleTracker();
BOOL Add(LPCTSTR szFile,
int nLine,
HANDLE handle,
LPCTSTR szMsg);
BOOL Remove(LPCTSTR szFile,
int nLine,
HANDLE handle);
private:
CPtrArray myHandleStringPairs;
HANDLE myMutex;
};
// ***********************
// HandleStringPair class:
// ***********************
class HandleStringPair
{
public:
HandleStringPair
(HANDLE handle,
LPCTSTR szMsg) :
myHandle(handle),
myString(szMsg) {}
HANDLE GetHandle()
{ return myHandle; }
const CString& GetString()
{ return myString; }
private:
HANDLE myHandle;
CString myString;
};
// *****************************
// HandleTracker implementation:
// *****************************
HandleTracker::HandleTracker()
{
myMutex =
CreateMutex
(0, // default security.
FALSE, // not owned.
NULL); // no name.
}
HandleTracker::~HandleTracker()
{
WaitForSingleObject
(myMutex, INFINITE);
if(myHandleStringPairs
.GetSize())
{
TRACE
("Detected resource"
"leaks!\n");
int nNumEntries =
myHandleStringPairs
.GetSize();
HandleStringPair *phsp;
for(int i = 0;
i < nNumEntries;
i++)
{
phsp =
static_cast
<HandleStringPair*>
(myHandleStringPairs
.GetAt(i));
if(phsp)
TRACE("%s\n",
(LPCTSTR)phsp
->GetString());
delete phsp;
}
}
else
TRACE
("No resource leaks "
"detected\n");
ReleaseMutex(myMutex);
CloseHandle(myMutex);
}
BOOL HandleTracker::Add
(LPCTSTR szFile,
int nLine,
HANDLE handle,
LPCTSTR szFunction)
{
char szMsg[MAX_PATH + 32];
sprintf(szMsg, "%s(%d) : "
"created in %s",
szFile, nLine,
szFunction);
HandleStringPair *phspToAdd;
try
{
phspToAdd =
new HandleStringPair
(handle, szMsg);
}
catch(CMemoryException *pMX)
{
pMX->Delete();
return FALSE;
}
WaitForSingleObject
(myMutex, INFINITE);
myHandleStringPairs
.Add(phspToAdd);
ReleaseMutex(myMutex);
return TRUE;
}
BOOL HandleTracker::Remove
(LPCTSTR szFile,
int nLine,
HANDLE handle)
{
WaitForSingleObject
(myMutex, INFINITE);
int nNumEntries =
myHandleStringPairs
.GetSize();
HandleStringPair *phsp;
for(int i = 0;
i < nNumEntries;
i++)
{
phsp =
static_cast
<HandleStringPair*>
(myHandleStringPairs
.GetAt(i));
if(phsp &&
phsp->GetHandle()
== handle)
{
myHandleStringPairs
.RemoveAt(i);
myHandleStringPairs
.FreeExtra();
delete phsp;
break;
}
}
ReleaseMutex(myMutex);
if(i >= nNumEntries)
{
TRACE
("HandleTracker::Remove"
" - Couldn't find"
" handle 0x%x, closed"
" in %s, line %d\n",
handle, szFile, nLine);
return FALSE;
}
return TRUE;
}
// *********************
// Create one static
// HandleTracker object:
// *********************
static HandleTracker
TheHandleTracker;
// *************************
// Function implementations:
// *************************
HANDLE DEBUG_CREATE_MUTEX
(LPCTSTR szFile, int nLine,
LPSECURITY_ATTRIBUTES lpsa,
BOOL bInitiallyOwned,
LPCTSTR szMutexName)
{
HANDLE hMutex =
CreateMutex(lpsa,
bInitiallyOwned,
szMutexName);
if(hMutex)
{
TheHandleTracker.Add
(szFile, nLine, hMutex,
"CreateMutex");
}
return hMutex;
}
BOOL DEBUG_CLOSE_HANDLE
(LPCTSTR szFile,
int nLine,
HANDLE handle)
{
TheHandleTracker.Remove
(szFile, nLine, handle);
return CloseHandle(handle);
}
#endif // _DEBUG
//End of File