摘 要:
内存池
1.避免内存频繁的分配和释放。
2.即便内存的使用者忘记释放内存,那么这些内存也不会丢失,它们仍然保存在内存池中,当内存池被销毁的时候这些内存将自动的被销毁。
MemPool.cpp
此代码收录在中焯COM32项目中。
1.避免内存频繁的分配和释放。
2.即便内存的使用者忘记释放内存,那么这些内存也不会丢失,它们仍然保存在内存池中,当内存池被销毁的时候这些内存将自动的被销毁。
3.实现内存动态可变大小分配,打破以往简易内存池固化大小的限制。
MemPool.h
#pragma once #include <list> using namespace std; //内存池 class CMemPool { public: //uMaxSize:阀值 CMemPool(UINT uMaxFree = 5); virtual ~CMemPool(void); //列表节点 struct list_node { list_node():size(0),pbuf(NULL) {} UINT size; char* pbuf; }; typedef list<list_node> LISTMEMORY; typedef list<list_node>::iterator ITLISTMEM0RY; public: //初始化阀值 uMaxSize:阀值 void InitMem(UINT uMaxFree); //申请内存 char * NewMem(size_t size); //释放内存 void FreeMem(char * pbuf); //释放所有内存 void FreeAllMem(); protected: //分配一块新的内存 - 使用在临界区内 char * Newbuf(size_t size); //获取最大内存块大小 - 使用在临界区内 UINT GetMaxBuf(); private: CRITICAL_SECTION m_cris; //缓存临界区 LISTMEMORY m_listFree; //空闲的内存块 LISTMEMORY m_listUsed; //使用中的内存块 UINT m_uMaxFree; //空闲内存阀值,超过此阀值可直接释放-返还给系统 };
MemPool.cpp
#include "StdAfx.h" #include "MemPool.h" #include <assert.h> CMemPool::CMemPool(UINT uMaxFree/* = 5*/) : m_uMaxFree(uMaxFree) { //判断参数是否合法 assert(uMaxFree); //临界区 InitializeCriticalSection(&m_cris); } CMemPool::~CMemPool(void) { EnterCriticalSection(&m_cris); ITLISTMEM0RY it; //释放空闲队列内存 if (!m_listFree.empty()) { for(it = m_listFree.begin();it != m_listFree.end();it++) { if( (*it).pbuf ) delete[] (*it).pbuf; } m_listFree.clear(); } //释放使用状态的内存 if (!m_listUsed.empty()) { for(it = m_listUsed.begin();it != m_listUsed.end();it++) { if( (*it).pbuf ) delete[] (*it).pbuf; } m_listUsed.clear(); } LeaveCriticalSection(&m_cris); //删除临界区 DeleteCriticalSection(&m_cris); } //初始化阀值 void CMemPool::InitMem(UINT uMaxFree) { //判断参数是否合法 assert(uMaxFree); m_uMaxFree = uMaxFree; } //申请内存 char * CMemPool::NewMem(size_t size) { EnterCriticalSection(&m_cris); char * ptr = NULL; //判断当前是否有空闲内存块 if(!m_listFree.empty() && GetMaxBuf()>=size) { ITLISTMEM0RY it = m_listFree.begin(); for(; it!=m_listFree.end(); it++) { if( (*it).size >= size ) { ptr = (*it).pbuf; //把内存块放到使用队列中 m_listUsed.push_back(*it); m_listFree.erase(it); //退出 LeaveCriticalSection(&m_cris); return ptr; } } } //分配一块新的内存 try{ ptr = Newbuf(size); } catch(...) { } LeaveCriticalSection(&m_cris); return ptr; } //释放内存 void CMemPool::FreeMem(char * pbuf) { if (!pbuf) return; EnterCriticalSection(&m_cris); //在使用队列中查找要释放的内存块 ITLISTMEM0RY it = m_listUsed.begin(); for(;it != m_listUsed.end();++it) { if ( (*it).pbuf == pbuf) { //判断当前空闲队列是否大于初始值 if (m_listFree.size() < m_uMaxFree) { //如果小于阀值,则将内存块放到空闲队列 memset( (*it).pbuf,0, (*it).size); m_listFree.push_back(*it); } else { //判断当前空闲队列大于或等于阀值,则将内存块释放 if( (*it).pbuf ) delete[] (*it).pbuf; } //将内存块从使用队列中删除 m_listUsed.erase(it); break; } } LeaveCriticalSection(&m_cris); } //释放所有内存 void CMemPool::FreeAllMem() { //将使用列表中的内存块移至空闲列表 EnterCriticalSection(&m_cris); ITLISTMEM0RY it = m_listUsed.begin(); for(; it != m_listUsed.end() && m_listFree.size() < m_uMaxFree; it++) { if( (*it).pbuf && (*it).size) { memset( (*it).pbuf,0,(*it).size); m_listFree.push_back(*it); } } //超过阀值部分直接销毁 for(;it != m_listUsed.end(); it++) { if( (*it).pbuf ) delete[] (*it).pbuf; } //清空使用列表 m_listUsed.clear(); LeaveCriticalSection(&m_cris); } //分配一块新的内存 char * CMemPool::Newbuf(size_t size) { list_node node; //分配一块新的内存 node.pbuf = new char[size]; ASSERT(node.pbuf); if(!node.pbuf) return NULL; node.size = size; memset(node.pbuf,0,node.size);//清理内存 m_listUsed.push_back(node); return node.pbuf; } //获取最大内存块大小 UINT CMemPool::GetMaxBuf() { UINT uiMax = 0; ITLISTMEM0RY it = m_listFree.begin(); for(;it != m_listFree.end(); it++) { if( (*it).size > uiMax) uiMax = (*it).size; } return uiMax; }
此代码收录在中焯COM32项目中。