类实例跟踪统计管理器(源代码)

来源:互联网 发布:2016网络作家榜 编辑:程序博客网 时间:2024/06/02 00:33

在用VC++开发COM组件时,某些类实例没有被析构,从而导致内存泄露。即使类实例最终被析构,但没有在运行中按期望及时的析构,也说明程序设计存在缺陷。我们当然可以在每个类的析构函数中设置一个断点,实时跟踪实例的析构情况。但如果用这种方法对大量的类实例进行跟踪,就显得太繁琐了。

因此,我们可以设计一个机制,能自动跟踪类实例的创建和析构动作,并将统计信息实时的呈现出来(如写入IDE的output窗口,这样不会影响程序的正常运行)。这样,我们就可以定位问题出现在哪个类中,然后可以作进一步的分析。

下面,我们实现一个“类实例跟踪统计管理器”,包含在一个文件"TraceClass.h"中,可以按如下的方式呈现统计结果。

(分两行)
********* Total Class1 Class2 Class3
                   
4          3         1         0

使用方法也很简单:

  1. 当然是先包含头文件"TraceClass.h
  2. 在类(假设类名为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
原创粉丝点击