一个C++的内存池和内存管理的实现(三)
来源:互联网 发布:111111的网络语意思 编辑:程序博客网 时间:2024/04/28 01:06
继续我们的内存分配函数,下面是页的分配
bool MemPool::AllocPage(){ MemPageHeader *p = (MemPageHeader*) _aligned_malloc(MAX_ALLOC_FROM_PAGE * 2, 16); // 每个页2*2048个字节 if (p == NULL) return false; // 从系统申请内存失败 p->d.pLast = (char*) p + sizeof(MemPageHeader); p->d.pEnd = (char*) p + MAX_ALLOC_FROM_PAGE * 2; p->d.nMax = MAX_ALLOC_FROM_PAGE * 2; p->postf.pPrefix = NULL; p->postf.dwCheckSum = PAGE_POSTFIX_SIG; // 设为某个签名,用来表示这个后缀对应于一个页的头部,而不是普通的内存块的后缀。有什么用?想想页的尾巴(pLast)向前移动寻找,看前面的内存块是否可以与尾部的空余内存块合并。怎么知道前面的是个普通内存块还是已经到页的头部了呢? p->d.pNext = m_pFirstPage; m_pFirstPage = p; return true;}
下面用于申请一块大于2048字节的内存:
void* MemPool::AllocLarge(int nSize, const char* const szFileName, int nLine, bool bIsArray){ Prefix *pPrefix = (Prefix*) _aligned_malloc(sizeof(Prefix) + nSize + sizeof(Postfix), 16); if (pPrefix) { pPrefix->d.pPostfix = (Postfix*)(pPrefix->pMem + nSize); pPrefix->d.pPostfix->pPrefix = pPrefix; pPrefix->d.pPage = NULL; // 表明它不是从页里分配的 // 插入大内存块的链表头和第一个有效元素(如果有的话)之间 pPrefix->d.pNext = m_pLarge->d.pNext; if (m_pLarge->d.pNext) m_pLarge->d.pNext->d.pPrev = pPrefix; m_pLarge->d.pNext = pPrefix; pPrefix->d.pPrev = m_pLarge; return pPrefix->pMem; // 返回真正使用的内存块地址 } std::cerr << "Memory allocation failure" << std::endl; return NULL;}
接下来是我们的另一个重头函数,内存释放函数:
void MemPool::Free(void* pMem){ SYNCHRONIZATION(); // 线程安全的宏,这里不用细究 Prefix *pPrefix = (Prefix*) pMem - 1; // 得到对应的前缀地址 if (pPrefix->d.pPage) // 从页里分配的 { int nSize = (int) ((INT_PTR) pPrefix->d.pPostfix - (INT_PTR) pPrefix->pMem); int nMinPower2 = 16; int i = 0; for (; nMinPower2 < nSize; nMinPower2 = nMinPower2 << 1, i ++); // 得到该尺寸对应的索引 m_nBlocksAllocated[i] --; // 计数分配的该尺寸内存块 MemPageHeader *pPage = pPrefix->d.pPage; if (pPage->d.pLast == (char*) (pPrefix->d.pPostfix + 1)) // 紧接页尾,可合并 { pPage->d.pLast = (char*) pPrefix; // 合并 do { // 继续检查前面的内存块使用中还是在池里(即是否有可以继续合并的) Postfix *pPostfix = (Postfix*) pPage->d.pLast - 1; if (pPostfix->pPrefix == NULL && pPostfix->dwCheckSum == PAGE_POSTFIX_SIG) break; // 已经到页头了 pPrefix = pPostfix->pPrefix; if (IsInBlockPool(pPrefix)) // 在某个尺寸的内存池中 { // 从对应尺寸的内存池中分离 Prefix *p1 = pPrefix->d.pPrev, *p2 = pPrefix->d.pNext; p1->d.pNext = p2; if (p2) p2->d.pPrev = p1; pPage->d.pLast = (char*) pPrefix; // 合并 } else break; } while (true); } else // 不在页尾,无法合并 { // 插入对应尺寸的内存池链表头和第一个有效元素之间 pPrefix->d.pNext = m_ppBlockPools[i]->d.pNext; if (m_ppBlockPools[i]->d.pNext) m_ppBlockPools[i]->d.pNext->d.pPrev = pPrefix; m_ppBlockPools[i]->d.pNext = pPrefix; pPrefix->d.pPrev = m_ppBlockPools[i]; pPrefix->d.pPostfix->nBlockPoolIndex = i; } } else // 大内存 { // 将该内存块从大内存链表中分离 Prefix *p1 = pPrefix->d.pPrev, *p2 = pPrefix->d.pNext; p1->d.pNext = p2; if (p2) p2->d.pPrev = p1; // 释放 _aligned_free(pPrefix); }}
好了,内存池的实现就这些了,除了还有一个添加清理函数的东西还没放进来。这个先不弄了。以后再说。
什么,说好的overload的new和delete呢?现在这两个Alloc和Free函数怎么用?
下回再说
0 0
- 一个C++的内存池和内存管理的实现(三)
- 一个C++的内存池和内存管理的实现(一)
- 一个C++的内存池和内存管理的实现(二)
- 一个C++的内存池和内存管理的实现(四)
- 一个C++的内存池和内存管理的实现(五)
- 一个C++的内存池和内存管理的实现(六)
- 一个C++的内存池和内存管理的实现(七)
- 一个C++的内存池和内存管理的实现(八)
- 一个C++的内存池和内存管理的实现(九)
- 实现一个内存池管理的类
- Objective-C内存管理教程和原理剖析(三)@property (retain)和@synthesize的默认实现
- Objective-C内存管理教程和原理剖析(三)@property (retain)和@synthesize的默认实现
- Objective-C内存管理教程和原理剖析(三)@property (retain)和@synthesize的默认实现
- 内存的管理(三)
- 【C++】动态内存管理(三)不同的资源管理对象的实现
- 一个动态内存管理模块的实现
- 一个动态内存管理模块的实现
- c 的内存管理
- HDU 4606 Occupy Cities (计算几何+Floyd+二分+最小路径覆盖)
- sjkghskgdfsgdf
- 安卓实习期间整理知识点(八)
- sjgsghdsghdfs
- 关于longlong与位运算
- 一个C++的内存池和内存管理的实现(三)
- 构建自己的搜索引擎之Lucene详解
- UDP和TCP中的伪首部
- poj1011
- sdgsdjg123363dsgsdfsj
- 小小智力题
- LeetCode之Word Ladder
- hjkgjksgh324723sdfsdhus
- shjthwhls