[原创]:改进的相对完善的c内存池

/**
*作者:netpetboy Email:[email protected]
*本程序为内存池解决方案
*程序设计中兼顾了小内存碎片中等内寻管理以及大块内存
*设计中参阅了网络的部分内存池设计原理,取其精华,本程序池对象分为三个部分,(0-InitMemPool)*Align(4,8,16等等)大小
*范围内的内存申请在池链表的同时又一个池指针索引指向池,比如,设置InitMemPool为256,就会有256个被提前初始化,索引依次
*为1、2、3、...256,对应管理的内存片大小为1*Align、2*Align、3*Align.....256*Align,其中Align为基本对齐单位,默认为4,如果申
*请的内存比较大可以设置为8,前256(InitMemPool)个会索引指针,通过下标就能引用,大于此范围的内存在InitMemPool链表之后
*紧密附加在后面,不会产生空档,提起需要便利后面部分方能得到,当申请的内存大于255*255*Align的时候就超出了本内存池的管理范围
*一般来讲即使最小设置Align为4也可以达到260K的最大内存管理,如果不够用可以加大Align,再大了管理起来也就没意思了,内存管理的
*每块内存前面保留2个字符的unsigned short int类型的大小数据,用来保存数据块大小,方便free的时候使用
*本程序经过车是性能已经超过我所参考的大部分程序池,安全方面暂时没有加入线程锁,接下来的改进可能将锁保存在池链表中,对单项进行加锁
*/

memory.c


#include "memory.h"

static MemPool * heap=NULL;//分界线
static MemPool * top_of_heap=NULL;//池集合的头部
static MemPool * btm_of_heap=NULL;//池集合的尾部
int index=1;
MemPool * poolIndex[InitMemPool];
static long totalByte;
static Int AlignNum(Int size)
{
return (((size)+Align-1) &~ (Align-1));// 按Align对齐字节对齐
}
/**
*取会给定结构的池结构体
*/
MemPool * GetPool(unsigned int name)
{
MemPool * p=poolIndex[InitMemPool-1];
while(p->next!=heap->next)
{
if(p->name==name)
{
return p;
}
else
p=p->next;
}
return NULL;
}

/*新定义一个池项*/
MemPool *NewPoolItem(unsigned int name)
{
if(btm_of_heap!=NULL)
{
if(name<InitMemPool)
return poolIndex[Align-1];
else
{
if(heap->next!=NULL)
{
MemPool *p;
/*基本链表设置*/
heap->name=name;
heap->first=NULL;
heap->last=NULL;
heap->current=NULL;
/*设置杂项*/
heap->max_memory=0;
heap->init_item=0;
heap->per_expend_item=0;
heap->current_item=0;
heap->total_item=0;

p=heap;
heap=heap->next;
return p;
}
else
{
ExpendPool();
return NewPoolItem(name);
}
}
}
else
{
InitPool();
return NewPoolItem(name);
}
}
/*初始化池*/
void InitPool(void)
{
int blk;
MemPool *p;
heap=(MemPool *)malloc(sizeof(MemPool));/*创建第一个块*/
/*设置初始值*/
heap->name=1;/*设置第一个为1*Align的大小*/
heap->first=NULL;
heap->last=NULL;
heap->current=NULL;
/*设置杂项*/
heap->max_memory=0;
heap->init_item=0;
heap->per_expend_item=0;
heap->current_item=0;
heap->total_item=0;

heap->max_memory=10;
btm_of_heap=heap;
poolIndex[0]=heap;/*把第一个装入数组的第一个,以便索引适用*/
p=heap;
for(blk=1;blk<InitMemPool;++blk)
{
p->next=(MemPool *)malloc(sizeof(MemPool));
p=p->next;
/*设置初始值*/
p->name=blk+1;
p->first=NULL;
p->last=NULL;
p->current=NULL;
/*设置杂项*/
p->max_memory=0;
p->init_item=0;
p->per_expend_item=0;
p->current_item=0;
p->total_item=0;

poolIndex[blk]=p;/*装入剩下的部分到索引表*/

}
p->next=NULL;
top_of_heap=p;
heap=p;/*标示移动到poolIndex的最后面,如果有超出Index大小的新池就用这个指针来分隔标示*/


}
void ExpendPool(void)
{
int blk;
MemPool *p;
heap->next=(MemPool *)malloc(sizeof(MemPool));/*创建第一个块*/
heap=heap->next;
p=heap;
for(blk=1;blk<ExpendMemPool;++blk)
{
p->next=(MemPool *)malloc(sizeof(MemPool));
p=p->next;
}
p->next=NULL;
top_of_heap=p;
}
void FreePool(MemPool *p)
{
if(p!=NULL)
{
p->next=heap;
heap=p;
}
return;
}


/*初始化项*/
void InitItem(unsigned int name)
{
int blk;
MemItem *ip;/*项的链表指针*/
/*构造容器*/
MemPool *p;//=GetPool(name);
if(btm_of_heap==NULL)
{
p=NewPoolItem(name);
}
else if(name<=InitMemPool)
p=poolIndex[name-1];
else
p=GetPool(name);

p->total_item+=(p->init_item==0?InitMemItem:p->init_item);
p->first=(MemItem *)malloc(name*Align);/*创建第一个块*/

ip=p->first;
for(blk=1;blk<(p->init_item==0?InitMemItem:p->init_item);++blk)
{
ip->next=(MemItem *)malloc(name*Align);
ip=ip->next;
}
ip->next=NULL;
p->last=ip;
totalByte+=name*Align*(p->init_item==0?InitMemItem:p->init_item);

}
/*扩展当前池项的下属内存块*/
void ExpendItem(unsigned int name)
{
int blk;
MemItem *ip;/*项的链表指针*/
/*构造容器*/

MemPool *p;

if(name<=InitMemPool)
p=poolIndex[name-1];
else
p=GetPool(name);


p->total_item+=(p->per_expend_item==0?ExpendMemItem:p->per_expend_item);
p->last->next=(MemItem *)malloc(name*Align);/*创建第一个块*/
index++;
ip=p->last->next;
for(blk=1;blk<(p->per_expend_item==0?ExpendMemItem:p->per_expend_item);++blk)
{
ip->next=(MemItem *)malloc(name*Align);
ip=ip->next;
index++;
}
ip->next=NULL;
p->last=ip;
totalByte+=name*Align*(p->per_expend_item==0?ExpendMemItem:p->per_expend_item);
//printf("kuozan ");

}
/*申请心内存-〉内存池*/
void *New(unsigned int name)
{
//MemItem *ip;/*项的链表指针*/
/*构造容器*/
if(totalByte>MaxMemory)
return NULL;/**申请的总内存过大,请调大默认最大内存设置或者检察内寻泄露*/
if(name>=Align*255*255)
{
MemItem *ip=(MemItem *)malloc(name+2);
ip->size=0;
Short * size=(Short *)ip;
++size;/*移动short长度单位*/
return size;/*此处返回的是向后偏移过的指针*/
}
name=(((name+2)+Align-1) &~ (Align-1))/Align;
MemPool *p;
if(btm_of_heap==NULL)
{
p=NewPoolItem(name);
InitItem(name);
}

if(name<=InitMemPool)
p=poolIndex[name-1];
else
p=GetPool(name);


if(p->first!=NULL)
{
if(p->first->next!=NULL)
{
MemItem *ip;
ip=p->first;
p->first=p->first->next;
p->current_item++;
ip->size=name;
Short * size=(Short *)ip;//转化为Short指针
++size;/*移动short长度单位*/

return size;/*此处返回的是向后偏移过的指针*/
}
else
{
ExpendItem(name);
return New(name*Align-2);
}
}
else
{
InitItem(name);
return New(name*Align-2);
}
}
/*内存池回收*/
void Free(void *myp)
{
Short * size=(Short *)myp;//转化为Short指针
--size;/*向前移动short位移*/
MemItem *ip=(MemItem *)size;/*转化回来*/
MemPool *p;
if(ip->size==0)
{
free(ip);
return;
}
if(ip->size<=InitMemPool)
p=poolIndex[ip->size-1];
else
p=GetPool(ip->size);

if(p==NULL)
{
printf("试图释放一个不属于池的指针,直接释放了");
return;
}

if(p->first!=NULL)
{
ip->next=NULL;
p->last->next=ip;
p->last=p->last->next;
p->current_item--;
}
else
{
printf("产生了一个野指针");
}
return;
}
/*输出调试函数*/
void PrintPool(void)
{
MemPool * pool=btm_of_heap;
while(pool->next!=NULL)
{
printf("\n名称%i 共有%i 使用%i,初始化:%i 扩展%i 首地址%p 最后地址%p 当前地址%p 链表地 址:%p\n",pool->name,pool->total_item,pool->current_item,pool->init_item,pool->per_expend_item,pool->first,pool->last,pool->current,pool->next);
if(pool->total_item>0)
{
MemItem * mi=pool->first;
while(mi->next!=NULL)
{
printf("--\t%p",mi);
mi=mi->next;
}
}
pool=pool->next;
}
}

memory.h

#ifndef MemPool_H__
#define MemPool_H__
#define InitMemPool 10 //初始化池所能拥有的数量,不能超过255*255
#define ExpendMemPool 5 //每次扩展池多少项
#define Align 4 //对齐步进单位,4,8,16等等,每项所能容纳的最大内存为Align*index,index为short int,所以单项最大容量为Align*255*255字节,4字节对齐最大为260K,8字节对齐为512K
#define InitMemItem 100 //初始化池所能拥有的数量不能超过255*255
#define ExpendMemItem 100 //每次扩展池多少项。不能超过255*255
#define MaxMemory 1024*1024*300 //内存池最大容量 300M
#define new(type) ((type *)(New(sizeof(type))))
#define sizes sizeof(MemPool)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"

/**
*该结构用一个自增长的链表结构体保存分链表,每个结构体中包含具体链表的头部、尾部和空闲分界线指针,维护一个链表
*大致结构如下:
* MemPool
* V V V ...
* 链表1 链表2 链表3 ...
*通过这样一个结构系统就可以灵活增加减少系统池,并且可以控制池内结构,控制总数据量
*
*/

typedef union _MemItem MemItem;
typedef struct _MemPool MemPool;

union _MemItem
{
MemItem *next;
Short size;
};

/*池集合*/
struct _MemPool
{
int name;//名称,同item_size,不管什么类型,申请的同一大小内存快放在同一个内存管理区域,视为同一名称,
long max_memory;//最多占用的内存
int init_item;//初始化多少item
int per_expend_item;//每次扩展时一次申请多少项
int current_item;//当前有多少项被使用
int total_item;//共有多少项
MemItem * first;//IO池头地址
MemItem * last;//IO池最后一项的地址
MemItem * current;//IO池分割空闲和使用中的分割地址
MemPool *next;//自身的链表结构
};


/**
*取会给定结构的池结构体
*/
static Int AlignNum(Int size);
MemPool * GetPool(unsigned int name);
MemPool *NewPoolItem(unsigned int name);
void InitPool(void);/*初始化池*/
void ExpendPool(void);/*扩展池*/
void FreePool(MemPool * p);/*释放池*/


void InitItem(unsigned int name);//初始化具体项的链表
void *New(unsigned int name);//初始化具体项的链表
void ExpendItem(unsigned int name);//初始化扩展项的链表
void Free(void *myp);//释放具体一项
void PrintPool(void);

#endif

你可能感兴趣的:(数据结构,C++,c,C#)