风魂引擎学习之使用内存池
时间:2010-12-13 来源:yezizhe
假如我们现在已经实现了一个自己的内存池,表现为一个类,接下来要做的事情就是使用它。这个过程是通过重载operator new和operator delete等相关函数实现的。(不清楚operator new,可以看下区分new ,operator new, placement new)。
先假设我们已经实现的内存池:

class CMemoryPool
{
public:
staticCMemoryPool *instance(){static CMemoryPool pool;return &pool;}
void*PoolAlloc(intsize){return malloc(size);}
voidPoolDelete(void*p){free(p);}
};
好吧,我承认这东西算不上内存池,不过必要的信息都有了,首先是一个单例模式的对象,然后还有PoolAlloc和PoolDelete函数。接下来写个运行函数:
int main(int argc, _TCHAR* argv[])
{
int*p = new int(1);
deletep;
return0;
}
main函数只是生成了一个int的指针然后删除,接下来就是需要重载全局的operator new函数和operator delete函数去调用内存池的alloc和delete函数了。加入以下代码:

inline void * __cdecl operator new(unsigned int size)
{
returnCMemoryPool::instance()->PoolAlloc(size);
};
inline void __cdecl operator delete(void *p)
{
CMemoryPool::instance()->PoolDelete(p);
};
通过设置断点或者写个printf个语句,会发现全局的new和delete函数确实被我们重载了,指向了自己实现的内存池的函数。
实现内存池还有一个很重要的作用,就是可以记录内存相关的使用情况,特别是最后进行内存泄露检查,输出包括文件名和行数等调试信息。而这也是通过重载operator new函数,不过参数就多了些,函数原型:
inline void * __cdecl operator new(unsigned int size, const char *file, int line)
{
returnCMemoryPool::instance()->PoolAlloc(size, file, line);
};
这里看见CMemoryPool有个PoolAlloc的重载函数,参数除了size,还有跟operator new对应的file和line的信息。我们在内存池这样子实现它:
void *PoolAlloc(unsigned int size, const char *file, int line) {return malloc(size);}
嗯,我们并没有记录file和line的信息,但是知道被调用了即可。
最后一步,也是最重要的工作,系统默认调用的operator new是不带file和line信息的,我们想调用的是带调试信息的operator new,所以加入以下代码:
#ifdef _DEBUG
#define DEBUG_NEW new(__FILE__, __LINE__)
#else
#define DEBUG_NEW new
#endif
我们还必须加上开关函数#define new DEBUG_NEW。首先将new定义为DEBUG_NEW,然后DEBUG_NEW又根据是否debug模式下调用不同operator new函数。好了,还是printf个语句或者F9下,看看file和line的信息是否正确。
那到底__FILE__, __LINE__和如何传递给函数的呢,好吧,是编译器的功劳,我们只需要提供好接口就可以了。
operator new(unsignedint size, const char *file, int line) 只有在debug版下才有意义,因此我们还是给他加上#ifdef _DEBUG和#endif 吧。
另外,我们还需要重载operator new[]和operator delete[],这里就省略了。
最后看下完整的代码:

#include "stdafx.h"
#include <malloc.h>
class CMemoryPool
{
public:
staticCMemoryPool *instance(){static CMemoryPool pool;return &pool;}
void*PoolAlloc(unsignedint size){return malloc(size);}
voidPoolDelete(void*p){free(p);}
void*PoolAlloc(unsignedint size, const char *file, int line) {return malloc(size);}
};
inline void * __cdecl operator new(unsigned int size)
{
printf("CMemoryPool::instance()->PoolAlloc %d\n",size);
returnCMemoryPool::instance()->PoolAlloc(size);
};
inline void __cdecl operator delete(void *p)
{
CMemoryPool::instance()->PoolDelete(p);
printf("CMemoryPool::instance()->PoolDelete\n");
};
#ifdef _DEBUG
inline void * __cdecl operator new(unsigned int size, const char *file, int line)
{
printf("CMemoryPool::instance()->PoolAlloc %d file:%sline:%d\n", size, file, line);
returnCMemoryPool::instance()->PoolAlloc(size, file, line);
};
#endif
#ifdef _DEBUG
#define DEBUG_NEW new(__FILE__, __LINE__)
#else
#define DEBUG_NEW new
#endif
int _tmain(int argc, _TCHAR* argv[])
{
#define new DEBUG_NEW
int*p = new int(1);
deletep;
#undef new
int*q = new int(1);
deleteq;
return0;
}
运行后输出:
CMemoryPool::instance()->PoolAlloc 4 file:c:\test1\test1.cpp line:49
CMemoryPool::instance()->PoolDelete
CMemoryPool::instance()->PoolAlloc 4
CMemoryPool::instance()->PoolDelete
希望文章对你有用,转载请说明出处。