CMemoryState(MFC内存检测类)(转)

MFC中的CMemoryState 类。
  这个类非常有用,它可以给当前内存照个快照,并可以将内存快照进行比对。如果你想确认程序在某个时段中分配的内存全部被正确的释放,那可以在这个时段开始时照个快照,结束后再照一个。如果这个两个快照不一样,说明这个时段中有内存泄漏了。
  这个类很容易使用。MSDN上的说明很清楚,还有一个例子。
  EMule在Emule.cpp文件中申明了这个类的三个静态变量
static CMemoryState oldMemState, newMemState, diffMemState;
  在BOOL CemuleApp::InitInstance()方法中就用到了它们。方法开始处先照了个快照。
oldMemState.Checkpoint();
  在该方法快结束时双照了一个并进行了比较,如果不一样,就说明有内存泄漏了。把泄漏的内存情况导出到output窗口。
newMemState.Checkpoint();
if (diffMemState.Difference(oldMemState, newMemState))
{
   TRACE("Memory usage:\n");
   diffMemState.DumpStatistics();
}
  一般可以用_DEBUG宏控制让这些代码只在调试阶段被编译。
  虽然这个类是MFC中的,其实是包装了Run-Time中几个Debug方法,但用起来很方便。如果不想用MFC,也可以直接把这个类抠出来用就是了。我就是这么干的,因为我都是用WTL。
  值得注意的是,快照的时机要掐准。最好是在刚开始就在关键部位掐好,每加入一点新功能就跑一跑。这种方式可以在程序一出现内存泄漏时就让你知道。在晚期再加这个机制就没什么用了,因为它并不能分析和定位内存泄漏。
  有一种情况要注意一下。如果掐的时机不准,很容易误报。比如我在main函数的开始和结尾掐快照,直觉上觉得应该是没问题了。但是如果程序中有一个全局对象,那么它会在main()之前被构造。假如这个对象有一个成员变量是一个STL::string,构造时为空,但在程序运行中给它赋了值。这时 string内部会new内存块出来。同样这个对象会在main()之后被析构,这时string内部new出来的内存才会被delete,但这已经超来了第二个快照的范围。这时两个快照是不一致的,但其实没有内存泄漏。
 
自己测试:
CMemoryState oldS,newS,diffS;

oldS.Checkpoint();
CBase* pBase1 = new CBase(1);
CBase* pBase2 = new CBase(2);
oldS.DumpAllObjectsSince();
newS.Checkpoint();

if(diffS.Difference(   oldS,  newS   ))
    cout<<"leaked"<<endl;

diffS.DumpStatistics(); 

 

posted on 2012-12-07 21:39  Rico Huang  阅读(267)  评论(0编辑  收藏  举报

导航