类实例跟踪统计管理器(源代码)
来源:互联网 发布:2016网络作家榜 编辑:程序博客网 时间:2024/06/02 00:33
在用VC++开发COM组件时,某些类实例没有被析构,从而导致内存泄露。即使类实例最终被析构,但没有在运行中按期望及时的析构,也说明程序设计存在缺陷。我们当然可以在每个类的析构函数中设置一个断点,实时跟踪实例的析构情况。但如果用这种方法对大量的类实例进行跟踪,就显得太繁琐了。
因此,我们可以设计一个机制,能自动跟踪类实例的创建和析构动作,并将统计信息实时的呈现出来(如写入IDE的output窗口,这样不会影响程序的正常运行)。这样,我们就可以定位问题出现在哪个类中,然后可以作进一步的分析。
下面,我们实现一个“类实例跟踪统计管理器”,包含在一个文件"TraceClass.h"中,可以按如下的方式呈现统计结果。
(分两行)
********* Total Class1 Class2 Class3
4 3 1 0
********* Total Class1 Class2 Class3
4 3 1 0
使用方法也很简单:
- 当然是先包含头文件"TraceClass.h"
- 在类(假设类名为Class1)中加入一行 _TRACE_CLASS(Class1) 即可。
源码如下:也可直接下载:http://download1.csdn.net/down3/20070522/22175433588.h
#pragma once
/**//* 类实例跟踪统计管理器 TraceClass.h
////作者: pimshell
////博客: http://blog.csdn.net/pimshell
////更新地址:http://blog.csdn.net/pimshell/archive/2007/05/22/1621254.aspx
////当前版本: Version 1.0 - 05/22/2007
////用途:
1、debug时,用于跟踪类实例的创建与销毁动作,统计类实例的个数,
并将统计结果写入Output窗口。
从而协助检测内存泄露情况。
2、release时,本跟踪统计代码不被编译。
////统计结果格式:
(分两行)
********* Total Class1 Class2 Class3
4 3 1 0
////使用举例:
class Class1
{
_TRACE_CLASS(Class1) //只需这一行代码
};
//(可选)
#define _TRACECLASS_MINWIDTH 10 //每个单元格最小的宽度
#define _TRACECLASS_PREFIX _T("~~~~~") //第一行的前缀
////期望:
为了更好的完善代码,如有好的建议请上博客回复,
也可以随时从“更新地址”下载最新的版本。
////更新地址:http://blog.csdn.net/pimshell/archive/2007/05/22/1621254.aspx
////版本修改历史:
1.0: - 初始版本
*/
#ifdef _DEBUG
#ifndef _TRACECLASS_MINWIDTH
#define _TRACECLASS_MINWIDTH 8
#endif
#ifndef _TRACECLASS_PREFIX
#define _TRACECLASS_PREFIX _T("*******")
#endif
//trace class manager
class CTraceClassManager
...{
public:
private:
CAtlMap<CString,LONG> m_oTraceMap;
CComAutoCriticalSection m_oTraceCS;
private:
inline void lock()
...{
m_oTraceCS.Lock();
}
inline void unlock()
...{
m_oTraceCS.Unlock();
}
private:
void trace()
...{
CString sOne,sTwo;
CString sLineOne,sLineTwo;
//
long nRefTotal=0;
POSITION pos=m_oTraceMap.GetStartPosition();
while(pos!=NULL)
...{
//next
CString sClassName;
LONG nRef;
m_oTraceMap.GetNextAssoc(pos,sClassName,nRef);
//trace
getTraceString(sClassName,nRef,sOne,sTwo);
sLineOne+=sOne;
sLineTwo+=sTwo;
//ref
nRefTotal+=nRef;
}
//total
getTraceString(_T("Total"),nRefTotal,sOne,sTwo);
sLineOne=sOne+sLineOne;
sLineTwo=sTwo+sLineTwo;
//prefix
getTraceString(_TRACECLASS_PREFIX,-1,sOne,sTwo);
sLineOne=sOne+sLineOne;
sLineTwo=sTwo+sLineTwo;
//rn
sLineOne+=_T(" ");
sLineTwo+=_T(" ");
//trace
ATLTRACE(sLineOne);
ATLTRACE(sLineTwo);
}
void getTraceString(LPCTSTR szName,long nRef,CString& sOne,CString& sTwo)
...{
//count
long nCount=(long)wcslen(szName)+1;
if(nCount<_TRACECLASS_MINWIDTH)
nCount=_TRACECLASS_MINWIDTH;
//one
CString sFormat;
sFormat.Format(_T("%%%ds"),nCount);
sOne.Format(sFormat,szName);
//linetwo
if(nRef==-1)
...{
sTwo.Format(sFormat,L"");
}
else
...{
sFormat.Format(_T("%%%dd"),nCount);
sTwo.Format(sFormat,nRef);
}
}
public:
//add class
void addClass(LPCTSTR szClassName)
...{
this->lock();
//set
POSITION pos=m_oTraceMap.Lookup(szClassName);
if(pos==NULL)
...{
m_oTraceMap.SetAt(szClassName,1);
}
else
...{
LONG nRef=m_oTraceMap.GetValueAt(pos);
m_oTraceMap.SetValueAt(pos,++nRef);
}
//trace
this->trace();
this->unlock();
}
//remove class
void removeClass(LPCTSTR szClassName)
...{
this->lock();
//set
POSITION pos=m_oTraceMap.Lookup(szClassName);
if(pos!=NULL)
...{
//if ref==0 neednot remove it.
LONG nRef=m_oTraceMap.GetValueAt(pos);
m_oTraceMap.SetAt(szClassName,--nRef);
}
//trace
this->trace();
this->unlock();
}
};
//global member of trace class manager
__declspec( selectany ) CTraceClassManager g_oTraceClassManager;
//trace class
template <class T>
class CTraceClass
...{
public:
CTraceClass(void)
...{
g_oTraceClassManager.addClass( T::_GetTraceClassName() );
}
public:
~CTraceClass(void)
...{
g_oTraceClassManager.removeClass( T::_GetTraceClassName() );
}
};
#endif
//macro
#ifdef _DEBUG
#define _TRACE_CLASS(T)
private:
CTraceClass<T> _oTraceClass;
public:
static CString _GetTraceClassName()
...{
USES_CONVERSION;
return CString(A2T(#T));
}
#else
#define _TRACE_CLASS(T)
#endif
/**//* 类实例跟踪统计管理器 TraceClass.h
////作者: pimshell
////博客: http://blog.csdn.net/pimshell
////更新地址:http://blog.csdn.net/pimshell/archive/2007/05/22/1621254.aspx
////当前版本: Version 1.0 - 05/22/2007
////用途:
1、debug时,用于跟踪类实例的创建与销毁动作,统计类实例的个数,
并将统计结果写入Output窗口。
从而协助检测内存泄露情况。
2、release时,本跟踪统计代码不被编译。
////统计结果格式:
(分两行)
********* Total Class1 Class2 Class3
4 3 1 0
////使用举例:
class Class1
{
_TRACE_CLASS(Class1) //只需这一行代码
};
//(可选)
#define _TRACECLASS_MINWIDTH 10 //每个单元格最小的宽度
#define _TRACECLASS_PREFIX _T("~~~~~") //第一行的前缀
////期望:
为了更好的完善代码,如有好的建议请上博客回复,
也可以随时从“更新地址”下载最新的版本。
////更新地址:http://blog.csdn.net/pimshell/archive/2007/05/22/1621254.aspx
////版本修改历史:
1.0: - 初始版本
*/
#ifdef _DEBUG
#ifndef _TRACECLASS_MINWIDTH
#define _TRACECLASS_MINWIDTH 8
#endif
#ifndef _TRACECLASS_PREFIX
#define _TRACECLASS_PREFIX _T("*******")
#endif
//trace class manager
class CTraceClassManager
...{
public:
private:
CAtlMap<CString,LONG> m_oTraceMap;
CComAutoCriticalSection m_oTraceCS;
private:
inline void lock()
...{
m_oTraceCS.Lock();
}
inline void unlock()
...{
m_oTraceCS.Unlock();
}
private:
void trace()
...{
CString sOne,sTwo;
CString sLineOne,sLineTwo;
//
long nRefTotal=0;
POSITION pos=m_oTraceMap.GetStartPosition();
while(pos!=NULL)
...{
//next
CString sClassName;
LONG nRef;
m_oTraceMap.GetNextAssoc(pos,sClassName,nRef);
//trace
getTraceString(sClassName,nRef,sOne,sTwo);
sLineOne+=sOne;
sLineTwo+=sTwo;
//ref
nRefTotal+=nRef;
}
//total
getTraceString(_T("Total"),nRefTotal,sOne,sTwo);
sLineOne=sOne+sLineOne;
sLineTwo=sTwo+sLineTwo;
//prefix
getTraceString(_TRACECLASS_PREFIX,-1,sOne,sTwo);
sLineOne=sOne+sLineOne;
sLineTwo=sTwo+sLineTwo;
//rn
sLineOne+=_T(" ");
sLineTwo+=_T(" ");
//trace
ATLTRACE(sLineOne);
ATLTRACE(sLineTwo);
}
void getTraceString(LPCTSTR szName,long nRef,CString& sOne,CString& sTwo)
...{
//count
long nCount=(long)wcslen(szName)+1;
if(nCount<_TRACECLASS_MINWIDTH)
nCount=_TRACECLASS_MINWIDTH;
//one
CString sFormat;
sFormat.Format(_T("%%%ds"),nCount);
sOne.Format(sFormat,szName);
//linetwo
if(nRef==-1)
...{
sTwo.Format(sFormat,L"");
}
else
...{
sFormat.Format(_T("%%%dd"),nCount);
sTwo.Format(sFormat,nRef);
}
}
public:
//add class
void addClass(LPCTSTR szClassName)
...{
this->lock();
//set
POSITION pos=m_oTraceMap.Lookup(szClassName);
if(pos==NULL)
...{
m_oTraceMap.SetAt(szClassName,1);
}
else
...{
LONG nRef=m_oTraceMap.GetValueAt(pos);
m_oTraceMap.SetValueAt(pos,++nRef);
}
//trace
this->trace();
this->unlock();
}
//remove class
void removeClass(LPCTSTR szClassName)
...{
this->lock();
//set
POSITION pos=m_oTraceMap.Lookup(szClassName);
if(pos!=NULL)
...{
//if ref==0 neednot remove it.
LONG nRef=m_oTraceMap.GetValueAt(pos);
m_oTraceMap.SetAt(szClassName,--nRef);
}
//trace
this->trace();
this->unlock();
}
};
//global member of trace class manager
__declspec( selectany ) CTraceClassManager g_oTraceClassManager;
//trace class
template <class T>
class CTraceClass
...{
public:
CTraceClass(void)
...{
g_oTraceClassManager.addClass( T::_GetTraceClassName() );
}
public:
~CTraceClass(void)
...{
g_oTraceClassManager.removeClass( T::_GetTraceClassName() );
}
};
#endif
//macro
#ifdef _DEBUG
#define _TRACE_CLASS(T)
private:
CTraceClass<T> _oTraceClass;
public:
static CString _GetTraceClassName()
...{
USES_CONVERSION;
return CString(A2T(#T));
}
#else
#define _TRACE_CLASS(T)
#endif
- 类实例跟踪统计管理器(源代码)
- 跟踪实例
- 跟踪实例
- 配置VSS(源代码管理器)
- 文件管理器-android源代码
- DVD管理器源代码分享
- DVD管理器源代码分享
- 源代码管理器git
- 使用CocoaPods源代码管理器
- 调试跟踪Android源代码
- 跟踪Git 项目源代码
- android跟踪源代码
- 在线统计与跟踪
- crash统计跟踪工具
- Ecommerce Tracking - Web Tracking (ga.js)谷歌GA埋点web日志跟踪统计实例
- Android 文件管理器 Android文件管理器源代码
- 源代码实例
- C#.net源代码管理器问题
- 缓存技术探讨
- Photoshop 8.0 CS 视频教程--让你轻松成为美工高手
- 丁磊:那时候我们除了软件 什么也不会做
- 如何在NT Advanced Server上将sybase的total momory配到2G以上
- Sybase Adaptive Server 管理手册
- 类实例跟踪统计管理器(源代码)
- 第三部分 类和结构---------------
- 浅析Sybase数据库系统性能调优
- native2ascii的使用方法
- 分清全角和半角的区别
- 如何删除AD中的RMS根认证服务器
- .net c# Ajax下来菜单简单例子
- 移位运算符
- TurboLinux 下的SYBASE安装