C/C++中内存管理是个最麻烦的事情,内存申请释放,内存泄露,内存越界,甚至是内存碎片,就会导致程序出Core或者变慢。如何有效的管理内存,有很多方法,我认为最简单的方式是用一个内存池来管理内存。
谈到内存池的时候,就有必要说下程序的生命周期和作用域,数据分为三类:1类是进程数据(全局数据)。2、线程数据,每一个线程一份。3、请求数据,每一次调用一份。
如果一个内存池想什么生命周期和作用域的数据都放在里面,可能是不合适的。所以我建议的使用方式是:进程一个内存池、每一个线程一个内存池、每个请求一个内存池。
在进程/线程/请求初始时初始内存池,在进程/线程/请求结束时销毁内存池。
所以,就有了下面这个非常简单的内存池了,代码有一点点绕,不过仔细阅读还是能理解的。
头文件 AutoMemory.h
#ifndef _AUTO_MEMORY_H__
#define _AUTO_MEMORY_H__
#include <stddef.h>
//#define _MEM_TEST_
//#define _MEM_DEBUG_
#define _MEM_USE_
//default 1M
#define MEMORY_BLOCK_SIZE 1000000
/*
* 线程兼容,自动释放
*/
class AutoMemory
{
public:
AutoMemory();
AutoMemory(int block_size);
~AutoMemory();
void* Alloc(size_t size);
void Free(void* ptr);
void FreeAll();
void Debug();
int BlockCount();
size_t LeftSize();
size_t MemSize();
private:
struct MemBlock{
MemBlock* prev;
};
private:
int headerSize;
int blockSize;
size_t memSize;
int blockCount;
char* begin;
char* end;
//MemBlock* currBlock;
};
#endif
CPP文件AutoMemory.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "AutoMemory.h"
AutoMemory::AutoMemory(){
blockSize = MEMORY_BLOCK_SIZE;
blockCount = 0;
memSize = 0;
headerSize = sizeof(MemBlock);
begin = end = ( char* ) headerSize;
}
AutoMemory::AutoMemory(int block_size){
blockSize = block_size;
blockCount = 0;
memSize = 0;
headerSize = sizeof(MemBlock);
begin = end = ( char* ) headerSize;
}
AutoMemory::~AutoMemory(){
FreeAll();
}
size_t AutoMemory::MemSize(){
return memSize;
}
int AutoMemory::BlockCount(){
return blockCount;
}
size_t AutoMemory::LeftSize(){
return (size_t)(end-begin);
}
void AutoMemory::Debug(){
printf("Block count %d, Left size %d, Total size %d\n",
this->BlockCount(),
this->LeftSize(),
this->MemSize() );
}
void* AutoMemory::Alloc(size_t size){
#ifndef _MEM_USE_
return malloc(size);
#endif
if ( (size_t)( end - begin ) < size ){
if ( size >= blockSize){
char* ptr = (char*)malloc(headerSize + size);
MemBlock* pNew = (MemBlock*)ptr;
MemBlock* pHeader = (MemBlock*)(begin - headerSize);
if ( pHeader ){
pNew->prev = pHeader->prev;
pHeader->prev = pNew;
}else{
end = begin = (char*)( ptr + headerSize );
pNew->prev = NULL;
}
blockCount += 1;
memSize += size;
return end;
} else{
char* ptr = (char*)malloc(headerSize + blockSize);
MemBlock* pNew = (MemBlock*)ptr;
pNew->prev = (MemBlock*)(begin - headerSize);
begin = (char*)(ptr + headerSize);
end = begin + blockSize;
blockCount += 1;
memSize += blockSize;
}
}
return end -= size;
}
void AutoMemory::Free(void* ptr){
#ifndef _MEM_USE_
free( ptr );
#endif
}
void AutoMemory::FreeAll(){
MemBlock* pHeader = (MemBlock*)(begin - headerSize);
while( pHeader ){
MemBlock* pTemp = pHeader->prev;
free( pHeader );
pHeader = pTemp;
}
begin = end = (char*)headerSize;
memSize = 0;
blockCount = 0;
}
#ifdef _MEM_TEST_
int main(){
AutoMemory am(100);
printf("idx 1, alloc 10\n");
char* buf = (char*)am.Alloc(10);
am.Debug();
printf("idx 2, alloc 90\n");
am.Alloc(90);
am.Debug();
printf("idx 3, alloc 10\n");
am.Alloc(10);
am.Debug();
printf("idx 4, alloc 100\n");
am.Alloc(100);
am.Debug();
printf("idx 5, alloc 10\n");
am.Alloc(10);
am.Debug();
}
#endif