动态内存管理代码,求评价
时间:2010-08-29
来源:互联网
C/C++ code
#include "stdio.h" unsigned int free_tmp[1024*1024*2/4]={0}; //申请空间头结构 struct new_head{ unsigned int new_size; //申请空间块总大小 unsigned int magic; //合法性校验,值为(~new_size) }; //空闲空间头结构 struct free_head{ unsigned int free_size; //空闲块总大小 struct free_head * next; //下一个空闲块指针 unsigned int magic; //合法性校验,值为 (next+~free_size) }; struct free_head *global_first_pFreeHead; //全局 地址最低的空闲块 //初始化动态内存块 int free_init(void* start_add,unsigned int size) { global_first_pFreeHead = (struct free_head *)start_add; global_first_pFreeHead->next=NULL; global_first_pFreeHead->free_size=size; global_first_pFreeHead->magic=(unsigned int)global_first_pFreeHead->next+~global_first_pFreeHead->free_size; return 0; } //申请内存 void * new_n(unsigned int new_size) { struct free_head * p_free=NULL; //链表遍历指针 struct free_head * tmp=NULL; //暂存指针 struct new_head * new_tmp; //申请内存头指针 new_size=(((new_size-1)>>2)<<2)+4; //使申请字节数为4的倍数 for(p_free=global_first_pFreeHead;p_free!=NULL;p_free=p_free->next) //查找空闲块链表中符合要求的最小块 { /// for debug if(p_free->magic!=(unsigned int)p_free->next+~p_free->free_size) //检查空闲内存头合法性 { printf("堆栈检查错误!堆栈被破坏!\r\n"); 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) //从该空闲块中剥离申请空间 { struct free_head * store_tmp; p_free=tmp; store_tmp=p_free; p_free=(struct free_head *)(((char *)p_free)+new_size+sizeof(struct new_head)); p_free->free_size=store_tmp->free_size-(new_size+sizeof(struct new_head)); p_free->next=store_tmp->next; p_free->magic=(unsigned int)p_free->next+~p_free->free_size; if(store_tmp==global_first_pFreeHead) { global_first_pFreeHead=p_free; } } else return NULL; // 将剥离的空间初始化,并返回可用空间指针 new_tmp=(struct new_head *)tmp; new_tmp->new_size=new_size+sizeof(struct new_head); new_tmp->magic=~(new_tmp->new_size); return ((char *)new_tmp)+sizeof(struct new_head); } //释放空间 void free_n(void *p) { 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)); //指向申请内存头 if(p_tmp->new_size!=~p_tmp->magic) //检查内存头合法性 { printf("wrong pointer to be free is detected! free failed!"); 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;;) //将释放区域插入链表中 { /// for debug if(p_free->magic!=(unsigned int)p_free->next+~p_free->free_size) //检查空闲内存头合法性 { printf("堆栈检查错误!堆栈被破坏!\r\n"); return; } if(p_free==global_first_pFreeHead && p_free>p_new) //插入链表首位置 { global_first_pFreeHead=p_new; p_new->next=p_free; break; } if(p_free < p_new && p_free->next > p_new) //插入链表中间位置 { p_new->next=p_free->next; p_free->next=p_new; p_free->magic=(unsigned int)p_free->next+~p_free->free_size; break; } if(p_free->next==NULL) //插入链表末尾 { p_free->next=p_new; p_free->magic=(unsigned int)p_free->next+~p_free->free_size; p_new->next=NULL; break; } else { p_free=p_free->next; } } p_new->magic=(unsigned int)p_new->next+~p_new->free_size; for(p_free=global_first_pFreeHead;p_free!=NULL;p_free=p_free->next) //组合连续链表 { int flag1,flag2=NULL; do { flag1=NULL; if(p_free == (struct free_head *)((char *)p_free->next - p_free->free_size)) //判断连续性 { p_free->free_size = p_free->free_size + p_free->next->free_size;//必须先设置大小,然后再设置链表指针 p_free->next = p_free->next->next; flag1=!NULL; flag2=!NULL; } }while(flag1); if(flag2) p_free->magic=(unsigned int)p_free->next+~p_free->free_size; } } int _tmain(int argc, _TCHAR* argv[]) { unsigned int i=0; printf("%d %u",sizeof(int),i-1); free_init(free_tmp,1024*1024*2); int * p0=(int *)new_n(sizeof(int)); *p0=0x12345678; //free_n(p0); int *p1=(int *)new_n(sizeof(int)); *p1=0x77777777; //free_n(p0); int *p2=(int *)new_n(sizeof(int)*1); p2[0]=0x12341234; //p2[1]=0x66668888; int * p3=(int *)new_n(sizeof(int)*1); p3[0]=0x11111111; //p3[1]=0x22222222; //p3[2]=0x33333333; free_n(p0); free_n(p2); free_n(p3); free_n(p1); return 0; }
作者: bluehousedahui 发布时间: 2010-08-29
作者: chuifeng56 发布时间: 2010-08-29
作者: lazy_2010 发布时间: 2010-08-29
如果能够支持内存泄漏的检测就更好了。
这个可以实现,在写一个遍历空闲内存链表的程序,如果程序程序结束时检查一下是否为一个整体的内存块就可以了。
作者: bluehousedahui 发布时间: 2010-08-29
作者: wing_0706 发布时间: 2010-08-29
另外,printf 这样的语句不知道在你的嵌入式系统中不知道是否可以,建议写一个 log 函数,在 log 函数中调用 printf,以后方面统一换成别的输出函数;
作者: lazy_2010 发布时间: 2010-08-30
主要在回收内存时,每一次都要全部遍历,这在效率上是无法接受的。
算法要考虑到“相邻块”就可以了。
作者: sinservice 发布时间: 2010-08-30
不能动态预分配?如果起不到内存池的作用,那在应用层封装一层这样的api有什么意义?
此外,可以考虑加上检测重复free,以及内存越界的检测。
作者: hairetz 发布时间: 2010-08-30
http://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html?ca=drs-cn
这篇可以看看哈
作者: hairetz 发布时间: 2010-08-30
纯顶
作者: cloudhsu 发布时间: 2010-08-30
unsigned int free_tmp[1024*1024*2/4]={0};
不能动态预分配?如果起不到内存池的作用,那在应用层封装一层这样的api有什么意义?
此外,可以考虑加上检测重复free,以及内存越界的检测。
那个数组纯粹是用VC模拟时构造出来的存储空间,在嵌入式里可以直接给出内存地址,不用那个数组了。
作者: bluehousedahui 发布时间: 2010-08-30
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28