编写内存分配器
来源:互联网 发布:淘宝rol是指什么 编辑:程序博客网 时间:2024/05/18 01:17
编写一个简单的分配器需要考虑以下问题:
1、空闲块的组织方式,选用的是隐式空闲链表
2、如何放置一个新分配的块,采用的是首次适配策略
3、如何合并空闲块
块的格式:使用边界标记的堆块的格式
定义4个字节为一个字,头部和脚部各一个字,内容相同。分别为块的大小和块的分配状态。采用双字对齐,因此最小块大小为16字节。脚部是为了便于合并空闲块而存在。
堆的格式
序言块和结尾块的存在也是为了便于合并。
我们的内存分配器运行于由memlib.c提供的内存模型之上。
memlib.c
#include <cstdlib>#include <iostream>static char *memHeap; //首地址static char *memBrk; //尾后地址static char *memMaxAddr; //最大边界地址static const unsigned int MAX_HEAP=1<<24;void mem_init(){ memHeap=(char*)(malloc(MAX_HEAP)); memBrk=memHeap; memMaxAddr=(char*)(memHeap+MAX_HEAP);}//分配额外的内存void *mem_sbrk(int incr){ char *old_brk=memBrk; if((incr<0)||((memBrk+incr)>memMaxAddr))//拒绝堆收缩请求和检测内存耗尽 { std::cout<<"error"; return (void*)-1; } memBrk+=incr; return (void*)old_brk;}
头文件提供一些简单的函数和函数接口
#include<cstddef>class mm{public: mm() {mmInit();} void mmFree(void *bp) //free { size_t size=getSize(hdrp(bp)); put(hdrp(bp),pack(size, 0)); //标记为空闲块 put(ftrp(bp),pack(size, 0)); coalesce(bp); //合并 } void *mmMalloc(size_t size); //mallocprivate: static const unsigned int WSIZE=4; //字长为4字节 static const unsigned int DSIZE=8; static const unsigned int CHUNKSIZE=1<<12; //默认分配块的大小 char *heapListP; //指向分配的第一个块,序言块 //方便操作的一组函数 unsigned int pack(unsigned int size,unsigned int alloc) {return (size|alloc);} unsigned int get(void *p) {return *((unsigned int *)(p));} void put(void *p,unsigned int val) {*((unsigned int *)(p))=val;} unsigned int getSize(void *p) {return get(p)&(~0x7);} unsigned int getAlloc(void *p) {return get(p)&(0x1);} char *hdrp(void *bp) {return ((char*)bp-WSIZE);} char *ftrp(void *bp) {return ((char*)bp+getSize(hdrp(bp))-DSIZE);} char *nextBlkP(void *bp) {return ((char*)bp+getSize(hdrp(bp)));} char *prevBlkP(void *bp) {return ((char*)bp-getSize((char*)bp-DSIZE));} int mmInit();//初始化堆 void *extendHeap(size_t words);//扩展堆,初始化的时候调用和找不到合适空闲块时调用 void *coalesce(void *bp); //合并空闲块 void *findFit(size_t size); //找到合适的分配块 void place(void *bp,size_t size); //放置分配块};
cpp文件
#include "mm.hpp"void *mem_sbrk(int incr);//初始化堆int mm::mmInit(){ heapListP=(char*)mem_sbrk(4*WSIZE); if(heapListP==(void*)-1) return -1; put(heapListP, 0); //起始位置,不使用的填充字 put(heapListP+(1*WSIZE),pack(DSIZE, 1)); //序言块 put(heapListP+(2*WSIZE),pack(DSIZE, 1)); put(heapListP+(3*WSIZE),pack(0, 1)); //结尾块 heapListP+=(2*WSIZE); //指向序言块 if(extendHeap(CHUNKSIZE/WSIZE)==nullptr) //初始分配一个默认块 return -1; return 0;}//扩展堆void *mm::extendHeap(std::size_t words){ size_t size; void * blockptr; size=(words%2)?(words+1)*WSIZE:words*WSIZE;//双字对齐 if((long)(blockptr=mem_sbrk(size))==-1) return nullptr; put(hdrp(blockptr),pack(size, 0));//结尾块变成分配块的头部 put(ftrp(blockptr),pack(size, 0));//分配块的脚部 put(hdrp(nextBlkP(blockptr)),pack(0, 1)); //新的结尾块 return coalesce(blockptr);//合并空闲块}//合并空闲块,一共四种情况。void *mm::coalesce(void *bp){ size_t prevAlloc=getAlloc(hdrp(prevBlkP(bp))); size_t nextAlloc=getAlloc(hdrp(nextBlkP(bp))); size_t size=getSize(hdrp(bp)); if(prevAlloc&&nextAlloc) { return bp; } else if(prevAlloc&&(!nextAlloc)) { size+=getSize(hdrp(nextBlkP(bp))); put(hdrp(bp), pack(size, 0)); put(ftrp(bp), pack(size, 0)); } else if(!prevAlloc&&nextAlloc) { size+=getSize(hdrp(prevBlkP(bp))); bp=prevBlkP(bp); put(hdrp(bp), pack(size, 0)); put(ftrp(bp), pack(size, 0)); } else { size+=getSize(hdrp(nextBlkP(bp)))+getSize(hdrp(prevBlkP(bp))); bp=prevBlkP(bp); put(hdrp(bp), pack(size, 0)); put(ftrp(bp), pack(size, 0)); } return bp;}//动态分配内存void *mm::mmMalloc(size_t size){ size_t asize; size_t extendSize; void *bp; if(size==0) return nullptr; if(size<=DSIZE) //最小块大小为16字节 asize=2*DSIZE; else asize=DSIZE*((size+DSIZE+(DSIZE-1))/DSIZE); //双字对齐 if((bp=findFit(asize))!=nullptr) { place(bp, asize); return bp; } extendSize=asize>CHUNKSIZE?asize:CHUNKSIZE; if((bp=extendHeap(extendSize/WSIZE))==nullptr) return nullptr; place(bp, asize); return bp;}//遍历块首次适配void *mm::findFit(size_t size){ char * bp=heapListP+DSIZE; while (getSize(hdrp(bp))) { if(getAlloc(hdrp(bp))) bp=nextBlkP(bp); else if (getSize(hdrp(bp))>=size) return bp; else bp=nextBlkP(bp); } return nullptr;}//放置块void mm::place(void *bp,size_t asize){ size_t size=getSize(hdrp(bp)); if(size-asize<2*DSIZE) { put(hdrp(bp), pack(size, 1)); put(ftrp(bp), pack(size, 1)); } else { put(hdrp(bp), pack(asize, 1)); put(ftrp(bp), pack(asize, 1)); void *nextBp=nextBlkP(bp); put(hdrp(nextBp), pack(size-asize, 0)); put(ftrp(nextBp), pack(size-asize, 0)); }}
main.c
#include "mm.hpp"void mem_init();int main(){ mem_init(); mm memory; int *p=(int*)memory.mmMalloc(sizeof(int)*100); memory.mmFree(p);}
阅读全文
0 0
- 编写内存分配器
- 内存分配器
- 内存分配器
- 内存分配器
- 简单内存分配器
- ACE内存分配器一
- ACE内存分配器二
- ACE内存分配器三
- STL的内存分配器
- STL中的内存分配器
- 快速的内存分配器
- GFP-Tree 内存分配器
- STL的内存分配器
- linux启动内存分配器
- [译文]SLUB 内存分配器
- TrafficServer内存分配器优化
- STL的内存分配器
- STL内存分配器:allocator
- ajax调用一般处理程序的多个方法
- WampServer 禁止目录列表显示 及目录权限跳转
- iCloud的使用方法
- 几个让代码读起来更舒服的小技巧
- 二十三种设计模式介绍
- 编写内存分配器
- Leetcode 算法习题 第十四周
- 简单实现SNMP获取系统信息以及网络接口信息
- EditText自定义下划线
- 学习目标(随时更新)
- php实现无限分类
- Jedis基本操作Demo
- TypeError: parse() got an unexpected keyword argument 'transport_encoding'
- 通讯报文中浮点类型的处理