You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
4.6 KiB
183 lines
4.6 KiB
/*--------------------------------------------------------------------------*
|
|
*
|
|
* Microsoft Windows
|
|
* Copyright (C) Microsoft Corporation, 1992 - 1999
|
|
*
|
|
* File: stddbg.cpp
|
|
*
|
|
* Contents: Implementation file for CDebugLeakDetector
|
|
*
|
|
* History: 26-Oct-98 jeffro Created
|
|
*
|
|
*--------------------------------------------------------------------------*/
|
|
#ifdef DBG
|
|
|
|
#include "windows.h"
|
|
#include "stddbg.h"
|
|
#include "tstring.h"
|
|
#include <map>
|
|
#include "atlbase.h" // USES_CONVERSION
|
|
//############################################################################
|
|
//############################################################################
|
|
//
|
|
// The safer string handling routines
|
|
//
|
|
//############################################################################
|
|
//############################################################################
|
|
#include <strsafe.h>
|
|
DECLARE_INFOLEVEL(AMCCore);
|
|
DECLARE_HEAPCHECKING;
|
|
|
|
|
|
class CDebugLeakDetector : public CDebugLeakDetectorBase
|
|
{
|
|
public:
|
|
CDebugLeakDetector()
|
|
{}
|
|
|
|
virtual ~CDebugLeakDetector()
|
|
{
|
|
DumpLeaks();
|
|
}
|
|
|
|
virtual void DumpLeaks()
|
|
{
|
|
RefCountsMap::iterator it;
|
|
std::string strError;
|
|
|
|
for (it = m_RefCounts.begin(); it != m_RefCounts.end(); ++it)
|
|
{
|
|
const std::string& strClass = it->first;
|
|
int cRefs = it->second;
|
|
|
|
if (cRefs != 0)
|
|
{
|
|
if (!strError.empty())
|
|
strError += "\n";
|
|
|
|
char szMessage[512];
|
|
int cchMessage = 512;
|
|
StringCchPrintfA (szMessage, cchMessage, "%s has %d instances left over",
|
|
strClass.data(), cRefs);
|
|
|
|
strError += szMessage;
|
|
}
|
|
}
|
|
|
|
if (!strError.empty())
|
|
::MessageBoxA(NULL, strError.data(), "MMC: Memory Leaks!!!", MB_OK | MB_SERVICE_NOTIFICATION);
|
|
}
|
|
|
|
virtual int AddRef(const std::string& strClass)
|
|
{
|
|
return (++m_RefCounts[strClass]);
|
|
}
|
|
|
|
virtual int Release(const std::string& strClass)
|
|
{
|
|
/*
|
|
* if this assert fails, you're releasing something that
|
|
* hasn't been addref'd -- check the spelling in your
|
|
* DEBUG_DECREMENT_INSTANCE_COUNTER macro usage
|
|
*/
|
|
ASSERT (m_RefCounts.find (strClass) != m_RefCounts.end());
|
|
|
|
/*
|
|
* If this assert fails, you have excessive releases.
|
|
* One possible cause of this is you might be using a
|
|
* compiler-generated copy constructor for your object,
|
|
* which won't call DEBUG_INCREMENT_INSTANCE_COUNTER.
|
|
* Define your own copy constructor.
|
|
*/
|
|
ASSERT (m_RefCounts[strClass] > 0);
|
|
|
|
return (--m_RefCounts[strClass]);
|
|
}
|
|
|
|
private:
|
|
class RefCounter
|
|
{
|
|
public:
|
|
RefCounter() : m_cRefs(0) {}
|
|
|
|
operator int()
|
|
{
|
|
return (m_cRefs);
|
|
}
|
|
|
|
int operator++() // pre-increment
|
|
{
|
|
return (++m_cRefs);
|
|
}
|
|
|
|
int operator++(int) // post-increment
|
|
{
|
|
int t = m_cRefs++;
|
|
return (t);
|
|
}
|
|
|
|
operator--() // pre-decrement
|
|
{
|
|
return (--m_cRefs);
|
|
}
|
|
|
|
int operator--(int) // post-decrement
|
|
{
|
|
int t = m_cRefs--;
|
|
return (t);
|
|
}
|
|
|
|
private:
|
|
int m_cRefs;
|
|
};
|
|
|
|
typedef std::map<std::string, RefCounter> RefCountsMap;
|
|
RefCountsMap m_RefCounts;
|
|
};
|
|
|
|
|
|
CDebugLeakDetectorBase& GetLeakDetector()
|
|
{
|
|
static CDebugLeakDetector detector;
|
|
return (detector);
|
|
}
|
|
|
|
DBG_PersistTraceData::DBG_PersistTraceData() :
|
|
bIComponent(false),
|
|
bIComponentData(false),
|
|
pTraceFN(NULL)
|
|
{
|
|
}
|
|
|
|
void DBG_PersistTraceData::SetTraceInfo(DBG_PersistTraceData::PTraceErrorFn pFn, bool bComponent, const tstring& owner)
|
|
{
|
|
ASSERT(pFn);
|
|
pTraceFN = pFn;
|
|
bIComponent = bComponent;
|
|
bIComponentData = !bComponent;
|
|
strSnapin = owner;
|
|
}
|
|
|
|
void DBG_PersistTraceData::TraceErr(LPCTSTR strInterface, LPCTSTR msg)
|
|
{
|
|
if (!pTraceFN)
|
|
return;
|
|
|
|
tstring formatted;
|
|
|
|
formatted += tstring(_T("\"")) + (strSnapin) + _T("\"");
|
|
|
|
formatted += tstring(_T(" Interface ")) + strInterface;
|
|
|
|
if (bIComponent)
|
|
formatted += _T("[IComponent]");
|
|
else if (bIComponentData)
|
|
formatted += _T("[IComponentData]");
|
|
|
|
formatted += _T(" - ");
|
|
formatted += msg;
|
|
|
|
pTraceFN(formatted.c_str());
|
|
}
|
|
|
|
#endif // DBG
|