#include "stdio.h"
//申请空间头结构
struct new_head{
unsigned int new_size; //申请空间块总大小
void * p_use;
unsigned int magic; //合法性校验,值为(p_user+new_size)
};
//空闲空间头结构
struct free_head{
unsigned int free_size; //空闲块总大小
struct free_head * prev; //上一个空闲块指针
struct free_head * next; //下一个空闲块指针
unsigned int magic; //合法性校验,值为 (prev+next+free_size)
};
//定义magic宏
#define NEW_MAGIC(var_addr) ((unsigned int)var_addr->p_use+var_addr->new_size)
#define FREE_MAGIC(var_addr) ((unsigned int)var_addr->prev + (unsigned int)var_addr->next + var_addr->free_size)
//错误码
#define HEAP_ERR 1 //堆检查错误
#define FREE_ERR 2 //释放指针错误
#define SIZE_ERR 3 //平台移植问题
struct free_head *global_first_pFreeHead; //全局 地址最低的空闲块
//错误处理打印函数
void _RamDP_error(int err_code, char * file_name, unsigned int line_num)
{
printf("***出现错误:%s中第%d行/r/n",file_name,line_num);
switch(err_code)
{
case HEAP_ERR:
//堆检查错误
printf("***堆检查错误,存在指针超范围使用。/r/n");
break;
case FREE_ERR:
//释放指针检查错误
printf("***指针检查错误,该指针已被释放或存在指针超范围使用。/r/n");
break;
case SIZE_ERR:
//平台移植性问题
printf("***存在平台移植性问题,可在struct free_head 或struct new_head中增加字符数组时表达式sizeof(free_head)和sizeof(new_head)+sizeof(int)大小相等。");
break;
default:
//
0;
}
while(1);
};
//初始化动态内存块
int free_init(void* start_add,unsigned int size)
{
if(sizeof(free_head)!=sizeof(new_head)+sizeof(int))
{
_RamDP_error(SIZE_ERR,__FILE__,__LINE__);
}
global_first_pFreeHead = (struct free_head *)start_add;
global_first_pFreeHead->free_size = (size/sizeof(int))*sizeof(int);
global_first_pFreeHead->prev = global_first_pFreeHead;
global_first_pFreeHead->next = NULL;
global_first_pFreeHead->magic = FREE_MAGIC(global_first_pFreeHead);
return 0;
}
/************************************/
/******** 申请内存函数 **************/
/*** 使用宏 new_n() 实现调试信息 ***/
#define new_n(new_size) New_SelfTest(new_size, __FILE__, __LINE__)
void * New_SelfTest(unsigned int new_size, char * file_name, unsigned int line_num)
{
struct free_head * p_free = NULL; //链表遍历指针
struct free_head * tmp = NULL; //暂存指针
struct new_head * new_tmp; //申请内存头指针
if(new_size == 0) return NULL;
new_size = (((new_size - 1) / sizeof(int) ) * sizeof(int)) + sizeof(int); //使申请字节数为sizeof(int)的倍数
for(p_free = global_first_pFreeHead; p_free != NULL; p_free = p_free->next) //查找空闲块链表中符合要求的最小块
{
/// for debug
if(p_free->magic != FREE_MAGIC(p_free)) //检查空闲内存头合法性
{
_RamDP_error(HEAP_ERR,file_name,line_num);
return NULL;
}
if(p_free->free_size >= (new_size + sizeof(struct new_head)))
{
if(tmp == NULL || tmp->free_size > p_free->free_size)
{
tmp = p_free;
}
}
}
if(tmp != NULL) //从该空闲块中剥离申请空间
{
p_free = (struct free_head *)(((char *)tmp) + new_size + sizeof(struct new_head));
if(p_free <= (struct free_head *)((char *)tmp + tmp->free_size - sizeof(struct free_head)))
{
p_free->free_size = tmp->free_size - (new_size + sizeof(struct new_head));
if(global_first_pFreeHead == tmp)
{
global_first_pFreeHead = p_free;
p_free->prev=p_free;
}
else
{
p_free->prev=tmp->prev;
}
p_free->next = tmp->next;
p_free->magic = FREE_MAGIC(p_free);
}
else
{
if(global_first_pFreeHead == tmp)
{
global_first_pFreeHead = tmp->next;
tmp->next->prev = tmp->next;
tmp->next->magic = FREE_MAGIC(tmp->next);
}
else
{
tmp->prev->next=tmp->next;
tmp->prev->magic=FREE_MAGIC(tmp->prev);
tmp->next->prev=tmp->prev;
tmp->next->magic=FREE_MAGIC(tmp->next);
}
}
}
else
return NULL;
// 将剥离的空间初始化,并返回可用空间指针
new_tmp = (struct new_head *)tmp;
new_tmp->new_size = new_size + sizeof(struct new_head);
new_tmp->p_use=((char *)new_tmp) + sizeof(struct new_head);
new_tmp->magic = NEW_MAGIC(new_tmp);
return new_tmp->p_use;
}
/************************************/
/******** 内存释放函数 **************/
/*** 使用宏 free_n() 实现调试信息 ***/
#define free_n(p) Free_SelfTest(p,__FILE__,__LINE__)
void Free_SelfTest(void *p,char * file_name, unsigned int line_num)
{
struct new_head * p_tmp; //
struct free_head * p_new; //
struct free_head * p_free; //链表遍历指针
unsigned int bytes_num; //记录释放空间大小
p_tmp = (struct new_head *)((char *)p - sizeof(struct new_head)); //指向申请内存头
p=NULL; //将p设为NULL,防止成为野指针。
if(p_tmp->magic != NEW_MAGIC(p_tmp)) //检查内存头合法性
{
_RamDP_error(FREE_ERR,file_name,line_num);
return;
}
bytes_num = p_tmp->new_size;//记录释放空间大小
p_new = (struct free_head *)p_tmp; //将该内存块变为空闲块
p_new->free_size = bytes_num;
for(p_free = global_first_pFreeHead; p_free != NULL; p_free = p_free->next) //将释放区域插入链表中
{
/// for debug
if(p_free->magic != FREE_MAGIC(p_free)) //检查空闲内存头合法性
{
_RamDP_error(HEAP_ERR,file_name,line_num);
return;
}
if(p_new < p_free) //插在当前快链的前面
{
if(global_first_pFreeHead == p_free)
{
global_first_pFreeHead = p_new;
p_new->prev = p_new;
}
else
{
p_new->prev = p_free->prev;
}
p_new->next = p_free;
p_free->prev = p_new;
p_free->magic = FREE_MAGIC(p_free);
break;
}
else if(p_new < p_free->next || p_free->next == NULL)
{
p_new->prev = p_free;
p_new->next = p_free->next;
p_free->next->prev = p_new;
p_free->next->magic = FREE_MAGIC(p_free);
p_free->next = p_new;
p_free->magic = FREE_MAGIC(p_free);
break;
}
}
p_new->magic = FREE_MAGIC(p_new);
if(p_new == (struct free_head *)((char *)p_new->prev + p_new->prev->free_size)) //判断前向连续性
{
p_new->prev->next = p_new->next;
p_new->prev->free_size += p_new->free_size;
p_new = p_new->prev;
p_new->magic = FREE_MAGIC(p_new);
}
if(p_new == (struct free_head *)((char *)p_new->next - p_new->free_size)) //判断后向连续性
{
p_new->free_size += p_new->next->free_size;
p_new->next = p_new->next->next;
p_new->magic = FREE_MAGIC(p_new);
}
}
/************************/
/******* 测试代码 *******/
/************************/
#include "stdio.h"
unsigned int free_tmp[1024*1024*2/4]={0}; //测试使用,为堆开辟空间。
int main(int argc, _TCHAR* argv[])
{
unsigned int i=0;
printf(" int类型字节数为:%d /r/n 无符号整形最大值为:%u /r/n 打印文件名: %s/r/n 行号: %d/r/n",sizeof(int),/
i-1,__FILE__,__LINE__);
free_init(free_tmp,1024*1024*2);
int * p0=(int *)new_n(sizeof(int));
*p0=0x12345678;
int *p1=(int *)new_n(sizeof(int));
*p1=0x77777777;
//free_n(p0);
free_n(p0);
p0=(int *)new_n(sizeof(int));
*p0=0x11223344;
int *p2=(int *)new_n(sizeof(int)*1);
p2[0]=0x12341234;
//p2[1]=0x66668888;
free_n(p1);
p1=(int *)new_n(sizeof(int));
*p1=0x11223344;
int * p3=(int *)new_n(sizeof(int)*1);
p3[0]=0x11111111;
//p3[1]=0x22222222;
//p3[2]=0x33333333;
free_n(p0);
//free_n(p0);
free_n(p2);
free_n(p3);
free_n(p1);
return 0;
}
资源消耗很小的内存池代码
最新推荐文章于 2024-09-14 22:25:22 发布