[C++之AOP]实战Aspect C++之检查内存泄漏

来源:转载

前面简单介绍了Aspect C++,相信没人看出它有什么特别强大的地方。

这次特别挑了一个合适的例子,检查内存泄漏。

首先看一个普通的程序:
1、test.h
#ifndef __TEST_H__
#define __TEST_H__

class Test1
{
};

class Test2
{
};

class Test3
{
};

#endif // __TEST_H__
2、main.cc
#include "test.h"

int main ()
{
Test1 test1;
Test2 test2;
Test3 test3;

new Test1();
new Test2();
new Test2();
new Test1();

new Test1(test1);
new Test3(test3);
return 0;
}

这个程序会有6个对象泄漏。如果是在很隐蔽的地方分配对象,如何能够快速查找出来呢?

采用Aspect C++,我们可以在构造函数和析构函数中插入代码,帮助检查内存泄漏。

首先实现一个内存分配记录管理器:
1、memory_recorder.h
#ifndef __MEMORY_RECORDER_H__
#define __MEMORY_RECORDER_H__

#include <map>
#include <typeinfo>
using namespace std;

class MemoryRecorder
{
map<void*, const type_info*> objects;
public:
~MemoryRecorder ();
void addObject(void* obj, const type_info& ti);
void removeObject(void* obj, const type_info& ti);
};

extern MemoryRecorder g_memoryRecorder;

#endif // __MEMORY_RECORDER_H__
2、memory_recorder.cc
#include "memory_recorder.h"

#include <iostream>
using namespace std;


MemoryRecorder g_memoryRecorder;


MemoryRecorder::~MemoryRecorder ()
{
if (objects.size() > 0)
{
cout << objects.size() << " objects not released:" << endl;
for (map<void*, const type_info*>::const_iterator iter = objects.begin();
iter != objects.end();
iter ++)
{
cout << "/t" << iter->second->name() << ": " << (iter->first) << endl;
delete (iter->first);
}
}
}

void MemoryRecorder::addObject(void* obj, const type_info& ti)
{
objects.insert(make_pair(obj, &ti));
}

void MemoryRecorder::removeObject(void* obj, const type_info& ti)
{
objects.erase(obj);
}
3、实现方面,test.ah
#ifndef __TEST_AH__
#define __TEST_AH__

#include "memory_recorder.h"
#include <iostream>
using namespace std;

aspect MemberRecorder
{
pointcut all_class() = classes("Test%");

advice construction (all_class()) : after ()
{
g_memoryRecorder.addObject (tjp->target(), typeid(*tjp->target()));
}

advice destruction (all_class()) : after ()
{
g_memoryRecorder.removeObject (tjp->target(), typeid(*tjp->target()));
}
};

#endif // __TEST_AH__

这个方面实现的功能很简单,首先定义了一个pointcut(切面),它匹配所有以“Test”开头的类。
接下来定义了2个处理方法,分别在这些类的构造函数和析构函数调用之后执行。

tjp->target()指向Test*对象实例,其它的不详细说明了,应该都比较容易懂。

顺便说一下,前一篇里说源文件可以保存为.cpp文件,实际上是错误的,它只处理.h和.cc文件。

运行ac++产生代码,编译运行后效果如下:
F:/projects/aspectc-out>main
6 objects not released:
class Test1: 00372B40
class Test1: 00372B70
class Test3: 00372BA0
class Test1: 00374F90
class Test2: 00374FC0
class Test2: 00374FF0

另外,产生代码时最好是使用mingw,配置方便一些,不影响产生后的代码,产生后的代码可以使用VC编译。



分享给朋友:
您可能感兴趣的文章:
随机阅读: