内存池代码,核心部分平台通用
#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;}