[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編譯。
轉自:http://www.cppblog.com/cpunion/archive/2005/12/16/1836.html
ACE
UNP
APUE
libevent
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章