【模版类】
这种方法有时候在查找内存泄漏的bug时可能会有用,该方法不需要修改实现类的任何代码,只需要修改该类继承一模版类即可,比较实用。下面介绍一下该模版类:
模版类头文件 dbgtrace.h:
#pragma once
// only support win32
#ifndef PRINT_FREQUENCY_NUMBER
#define PRINT_FREQUENCY_NUMBER 100
#endif
template <class T>
class CDbgClassObject
{
public:
CDbgClassObject();
virtual ~CDbgClassObject();
private:
LPCSTR GetName();
public:
static long m_lObjectsCount;
};
#define DECLARE_DEBUG_TEMPLATE_CLASS(Class) \
public CDbgClassObject<Class>
实现文件 dbgtrace.cpp:
#include "dbgtrace.h"
#include <typeinfo.h>
template <class T>
long CDbgClassObject<T>::m_lObjectsCount = 0;
template <class T>
CDbgClassObject<T>::CDbgClassObject()
{
InterlockedIncrement(&m_lObjectsCount);
if ((m_lObjectsCount % PRINT_FREQUENCY_NUMBER) == 0)
{
char szbuf[128];
sprintf(szbuf, "%s count = %ld.\n", GetName(), m_lObjectsCount);
OutputDebugStringA(szbuf);
}
}
template <class T>
CDbgClassObject<T>::~CDbgClassObject()
{
InterlockedDecrement(&m_lObjectsCount);
}
template <class T>
LPCSTR CDbgClassObject<T>::GetName()
{
const type_info& t = typeid(this);
return t.name();
}
【原理】
- 在模版类里声明一静态变量, 类构造时对此变量加1, 析构时减1,变量的值就是当前程序中存在的类实例的个数。
- 在获取当前实例的类名称时用到了函数typeid(this) 以获得实例的类型信息,从而将类的名字转换为字符串的形式。该函数只在Win32平台上才能用。
- PRINT_FREQUENCY_NUMBER 用来定义每创建多少个实例输出一次信息,如果定义为1, 则创建所有的实例都会输出信息。
【如何使用】
- 在需要跟踪的类头文件中添加
#include "dbgtrace.h"
,然后在类定义中添加从模版类继承:
DECLARE_DEBUG_TEMPLATE_CLASS(Class)
- 在类的cpp 文件中添加
#include "dbgtrace.cpp"
【举例说明】
程序中有一类CTest:
#pragma once
class CTest
{
public:
CTest(void);
~CTest(void);
};
cpp文件:
CTest::CTest(void)
{
}
CTest::~CTest(void)
{
}
- 修改头文件:
#include "dbgtrace.h"
class CTest : DECLARE_DEBUG_TEMPLATE_CLASS(CTest)
- 在cpp文件中添加
#include "dbgtrace.cpp"
- 测试代码:
在stdafx.h中定义
#define PRINT_FREQUENCY_NUMBER 1
#include "stdafx.h"
#include "Test.h"
int _tmain(int argc, _TCHAR* argv[])
{
CTest a;
CTest b;
CTest c;
CTest d;
CTest e;
CTest f;
return 0;
}
- 运行结果
class CDbgClassObject<class CTest> * count = 1.
class CDbgClassObject<class CTest> * count = 2.
class CDbgClassObject<class CTest> * count = 3.
class CDbgClassObject<class CTest> * count = 4.
class CDbgClassObject<class CTest> * count = 5.
class CDbgClassObject<class CTest> * count = 6.
可以看到, CTest类被创建了6次。