分享
 
 
 

打造自己的堆存储分配策略

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

#ifndef MEMORY_C

#define MEMORY_C

//#define TEST_MEMORY

#define IOS

#define DEBUG

//#define TEST_LITTLE

/*本系统开了一个特定大小的栈区,在这个区域上模拟堆存储管理

* 提供了两个关键的函数 malloc(int) 和free(void *)

*

* *这个版本的系统,使用了一个256k大小的栈

* 分成256大份,每份1k大小,

* 如果用户申请大于1k大小的空间,

* 则直接用伙伴算法通过大的Buddy_table(大表)找到一块合适大小的空闲块;

*

* 如果用户申请小于1k大小的空间,

* 则在一个1k的空闲块上,建立一个小的Buddy_table(小表)

* 一个小表管理32块,大小是32字节的小块。

* 一个小表分配完之后,建立新的一个小表,直到大表的空间也满为止

*

* 空间分配完的话,再申请空间时候,报memory full错

* */

#define NULL 0

#ifdef IOS

#include<iostream>

using namespace std;

#endif

#define malloc my_malloc

#define free my_free

#define UCHAR unsigned char

#define USHORT unsigned short

void * malloc(int size); //分配一段空间

void free(void *); //释放一个指针#define NULL 0

void free_little(void * addr);

void free_big(void * addr);

#define FALSE 0

#define TRUE 1

#define BIG_BLOCK_SIZE 1024 //大块每个1k

#define BIG_BLOCK_MAX 256//有多少个1k的大块

#define STACK_MAX BIG_BLOCK_SIZE*BIG_BLOCK_MAX //

#define BLOCKID_MAX 2*BIG_BLOCK_MAX //二叉树结点

//第一个结点分割1024*128+1024*128,第2,3个进一步分割

//1+2+4...+2^8=2^^9-1 ,

#define LITTLE_BLOCK_SIZE 32 //32个字节一个小块

#define LITTLE_BLOCK_MAX BIG_BLOCK_SIZE/LITTLE_BLOCK_SIZE //1024/32

#define LITTLE_BLOCKID_MAX 2*LITTLE_BLOCK_MAX

char SYS_STACK[STACK_MAX];//存储池

struct Buddy_address_table{

void * address[BIG_BLOCK_MAX];//起始地址

USHORT occu_id[BIG_BLOCK_MAX];//hash位置是否占用,0表示未占用,非0的话指向占用的id

bool semi[BLOCKID_MAX];//是否被部分占用,用这个数组表示一棵二叉

bool occupied[BLOCKID_MAX];//是否被完全占用,用这个数组表示一棵二叉树

};

Buddy_address_table bd={NULL};

struct Little_Buddy{

void * address[LITTLE_BLOCK_MAX];//起始地址

UCHAR occu_id[LITTLE_BLOCK_MAX];//hash位置是否占用,0表示未占用,非0的话指向占用的id

bool semi[LITTLE_BLOCKID_MAX];//是否被部分占用,用这个数组表示一棵二叉树

bool occupied[LITTLE_BLOCKID_MAX];//是否被完全占用,用这个数组表示一棵二叉树

int idx;//小表本身在大表中的idx(释放小表时要用到)

bool full;

};

void *find_little_space(Little_Buddy * lb,int i,int size,void * addr);

void * find_space(int i, int size,void * addr);

void error(int x){

#ifdef DEBUG

#endif

};

int big_size(int idx){

int s=STACK_MAX;

int i;

while(idx!=1){

s=s/2;

if(idx%2==0){

idx=idx/2;

}

else{

idx=(idx-1)/2;

}

}

return s;

}

int little_size(int idx){

int s=BIG_BLOCK_SIZE;

int i;

while(idx!=1){

s=s/2;

if(idx%2==0){

idx=idx/2;

}

else{

idx=(idx-1)/2;

}

}

return s;

}

//建立一个释放信息栈,每次受到释放信号的时候,不马上释放,而是先进栈

//栈满或者空间已经满时,一起释放,提高效率

//

Little_Buddy * lb_list[BIG_BLOCK_MAX]={NULL};

//最多BIG_BLOCK_MAX个小表--一个大BUDDY块可以是一个小BUDY表

int get_idx_little(Little_Buddy * lb, void *addr){

int i=(int)addr;

int k=i%LITTLE_BLOCK_MAX;

while(lb->occu_id[k]){

k++;

if(k==LITTLE_BLOCK_MAX){

k=0;

}

}

return k;//找到addre的插入位置

}

int get_idx(void *addr){

int i=(int)addr;

int k=i%BIG_BLOCK_MAX;

while(bd.occu_id[k]){

k++;

if(k==BIG_BLOCK_MAX){

k=0;

}

}

return k;//找到addre的插入位置

}

void * malloc(int size){

void * addr;

int idx;//查到的空闲块id

#ifdef DEBUG

cout<<"target space:"<<size<<endl;

#endif

if(size<=BIG_BLOCK_SIZE){//比较小的块,用小表分配

int i=0;

while(lb_list[i]!=NULL && lb_list[i]->full!=1){

#ifdef DEBUG

cout<<"search little"<<endl;

#endif

//已经建立的小表中,未满的表

if(addr=find_little_space(lb_list[i],1,size,lb_list[i])){

return addr;

}

i++;

}

//现有小表中找不到足够空间,建立新的小表

if(addr=find_space(1,BIG_BLOCK_SIZE,SYS_STACK)){//在大表中找到空间

lb_list[i]=(Little_Buddy*)addr;// 小表本身所占的空间

//little table initialize

int j;

for(j=0;j<LITTLE_BLOCKID_MAX;j++){

lb_list[i]->occupied[j]=FALSE;

lb_list[i]->semi[j]=FALSE;

}

for(j=0;j<LITTLE_BLOCK_MAX;j++){

lb_list[i]->occu_id[j]=0;

}

lb_list[i]->idx=idx;

//去掉小表本身的空间

find_little_space(lb_list[i],1,sizeof(Little_Buddy),addr);

//通过小表所描述的空闲块空间查找合适小空闲块

if(addr=find_little_space(lb_list[i],1,size,addr)){

return addr;

}

else{

return NULL;

}

}

}

return find_space(1,size,SYS_STACK);//从根结点开始找可用空间

}

//

//

void *find_little_space(Little_Buddy * lb,int i,int size,void * addr){

if(LITTLE_BLOCK_SIZE>size){size=LITTLE_BLOCK_SIZE;}

int sz=little_size(i);

if(LITTLE_BLOCKID_MAX<i){return NULL;}

if(lb->occupied[i]){return NULL;};

//半可用空间

if(lb->semi[i]){

#ifdef DETAIL

cout<<"semi"<<i<<" "<<sz<<" "<<size<<endl;

#endif

if(sz<=2*size){

return NULL;

}

else{

if(!lb->occupied[2*i]){

void * adr;

if(adr=find_little_space(lb,2*i,size,addr)){

return adr;

}

}

else{

char * ad=(char*)addr;

return find_little_space(lb,2*i+1,size,ad+sz/2);

}

}

}

//是完全可用空间

if(sz>=size){//存在可用空间

#ifdef DETAIL

cout<<"space:"<<i<<" "<<sz<<" "<<size<<endl;

#endif

if(sz>=2*size ){//还太大,继续分小的

lb->semi[i]==1;//本身半占

void * adr;

if (adr= find_little_space(lb,2*i,size,addr)){

return adr;

}

else{

char * ad=(char*)addr;

return find_little_space(lb,2*i+1,size,ad+sz/2);

};

}

//找到合适的可用空间

int k=get_idx_little(lb,addr);

lb->address[k]=addr;

lb->occu_id[k]=i;//记下对应地址的id 小表

lb->occupied[i]=TRUE;

#ifdef DEBUG

cout<<"space:"<<i<<" "<<sz<<" "<<size<<endl;

#endif

return addr;//返回存储空间首地址

}

else{

//所申请的块的大小已经超过这个小表的最大限度

lb->full=1;

return NULL;

}

}

//

//

void * find_space(int i, int size,void * addr){// 从 index开始找大小是size 的块

if(BIG_BLOCK_SIZE>size){size=BIG_BLOCK_SIZE;}

int sz=big_size(i);

#ifdef DETAIL

cout<<i<<" "<<sz<<" "<<size<<endl;

#endif

if(BLOCKID_MAX<i){return NULL;}

if(bd.occupied[i]){

#ifdef DETAIL

cout<<"occupied:"<<i<<endl;

#endif

return NULL;

}

//半可用空间

if(bd.semi[i]){

if(sz<=2*size){

return NULL;

}

else{

if(!bd.occupied[2*i]){

void * adr;

if(adr=find_space(2*i,size,addr)){

return adr;

}

}

else{

char * ad=(char*)addr;

return find_space(2*i+1,size,ad+sz/2);

}

}

}

//是完全可用空间

if(sz>=size){//存在可用空间

if(sz>=2*size ){//还太大,继续分小的

bd.semi[i]==1;//本身半占

void * adr;

if (adr= find_space(2*i,size,addr)){

return adr;

}

else{

char * ad=(char*)addr;

return find_space(2*i+1,size,ad+sz/2);

};

}

//找到合适的可用空间

int k=get_idx(addr);

bd.address[k]=addr;

bd.occu_id[k]=i;//记下对应地址的id 小表

bd.occupied[i]=TRUE;

#ifdef DEBUG

cout<<i<<" "<<sz<<" "<<size<<endl;

#endif

return addr;//返回存储空间首地址

}

else{

//所申请的块的大小已经超过这个表的最大限度

#ifdef DEBUG

cout<<"memory full"<<endl;

#endif

return NULL;

}

#ifdef DETAIL

cout<<"begin to assign "<<i<<endl;

#endif

if(!bd.occupied[i] && sz>size){//存在可用空间

if(sz>2*size){//还太大,继续分小的

bd.occupied[i]==TRUE;//本身不空

#ifdef DETAIL

cout<<"virtual assign"<<i<<" "<<sz<<endl<<endl;

#endif

void * adr;

if (adr= find_space(2*i,size,addr)){

bd.occupied[2*i]=1;//左结点不空

return adr;

}

else{

char * ad=(char *)addr;

bd.occupied[2*i+1]=1;//左结点不空

return find_space(2*i+1,size,ad+sz/2);

};

}

else{ //找到合适的可用空间

int k=get_idx(addr);

bd.address[k]=addr;

bd.occu_id[k]=i;//记下对应地址的id 小表

#ifdef DETAIL

cout<<"occu_id: "<<k<<" "<<(int)addr<<endl;

#endif

#ifdef DEBUG

cout<<"best suit:"<<i<<" "<<sz<<endl;

#endif

return bd.address[k];//返回存储空间首地址和空间大小

}

}

else{

#ifdef DETAIL

cout<<"begin search sub_node"<<endl;

#endif

if(bd.occupied[i]){//本块占用

void * adr;

if(adr=find_space(2*i,size,addr)){//找左结点

return adr;

} else{

char * ad=(char*)addr;

return find_space(2*i+1,size,ad+sz/2);

}

}

else{//所申请的块的大小已经超过最大限度

error(98);

#ifdef DEBUG

if(1==i){

cout<<"memory full"<<endl;

}

#endif

return NULL;

}

}

}

//

//

void free_big_id(int k){//释放上层虚结点

if(0==k){

#ifdef DEBUG1

cout<<"root "<<endl;

#endif

return;

}

if(1==k){

#ifdef DEBUG

cout<<"root freed"<<endl;

#endif

bd.occupied[1]=FALSE;//清空索引所指向的空间

bd.semi[1]=FALSE;//清空索引所指向的空间

return;

}

if(0==k%2){//左结点

#ifdef DETAIL

cout<<k<<" left virutal freed"<<endl;

#endif

if(!bd.occupied[k+1]|| !bd.semi[k+1]){//右边也空

#ifdef DETAIL

cout<<k+1<<" right blank too"<<endl;

#endif

free_big_id(k/2);

bd.occupied[k]=FALSE;//清空索引所指向的空间

bd.semi[k]=FALSE;//清空索引所指向的空间

}

}

else{//是右结点

#ifdef DETAIL

cout<<k<<" right virutal freed"<<endl;

#endif

if(!bd.occupied[k-1] || !bd.semi[k-1]){//左边也空

#ifdef DEBUG

cout<<k-1<<"left blank too"<<endl;

#endif

free_big_id((k-1)/2);

bd.occupied[k]=FALSE;//清空索引所指向的空间

bd.semi[k]=FALSE;//清空索引所指向的空间

}

}

}//end

//

//

int memory_size_little(void * addr){

int target=(int)addr;

int d;

for(int d=0;d<BIG_BLOCK_MAX;d++){

int head=(int)lb_list[d];

int tail=(int)((char*)lb_list[d]+BIG_BLOCK_SIZE);

if(target>=head &&target<tail){

int k=target%LITTLE_BLOCK_MAX;

Little_Buddy * p=lb_list[d];

while(p->address[k]!=addr ||!p->occu_id[k]){

k++;

if(k==BIG_BLOCK_MAX){

k=0;

}

}

return little_size(p->occu_id[k]);

}

}

return -1;

}

int memory_size_big(void * addr){

int target=(int)addr;

int head=target%BIG_BLOCK_MAX;

int tail=head;

#ifdef DETAIL

cout<<head<<" "<<(int)addr<<endl;

#endif

if(bd.address[head]==addr && bd.occu_id[head]!=0 ){

;

}

else{

head++;

while(

tail!=head &&

(bd.occu_id[head]==0 || bd.address[head]!=addr )

){

#ifdef DEBUG

// cout<<(int)bd.address[head]<<" ";

#endif

head++;

if(head==BIG_BLOCK_MAX){

head=0;

}

}

}

int k=head;

if(head==tail){

return memory_size_little(addr);

}

return big_size(bd.occu_id[k]);

}

//

void free_big(void * addr){

int target=(int)addr;

int head=target%BIG_BLOCK_MAX;

int tail=head;

#ifdef DETAIL

cout<<head<<" "<<(int)addr<<endl;

#endif

if(bd.address[head]==addr && bd.occu_id[head]!=0 ){

;

}

else{

head++;

while(

tail!=head &&

(bd.occu_id[head]==0 || bd.address[head]!=addr )

){

#ifdef DEBUG

// cout<<(int)bd.address[head]<<" ";

#endif

head++;

if(head==BIG_BLOCK_MAX){

head=0;

}

}

}

int k=head;

if(head==tail){

free_little(addr);

}

if(1==bd.occu_id[k]){//不是根结点

#ifdef DEBUG

cout<<"big root freed"<<endl;

#endif

bd.occupied[1]=FALSE;//清空索引所指向的空间

bd.semi[1]=FALSE;//清空索引所指向的空间

bd.occu_id[k]=0;//空出一个索引位置

return;

}

if(bd.occu_id[k]%2==0 ){//左结点

#ifdef DEBUG

cout<<bd.occu_id[k]<<"left real freed"<<endl;

#endif

if(!bd.occupied[bd.occu_id[k]+1]){//右边也空

free_big_id(bd.occu_id[k]/2);

}

}

else{//是右结点

#ifdef DEBUG

cout<<bd.occu_id[k]<<"right real freed"<<endl;

#endif

if(!bd.occupied[bd.occu_id[k]-1]){//左边也空

free_big_id((bd.occu_id[k]-1)/2);

}

}

bd.occupied[bd.occu_id[k]]=FALSE;//清空索引所指向的空间

bd.semi[bd.occu_id[k]]=FALSE;//清空索引所指向的空间

bd.occu_id[k]=0;//空出一个索引位置

}

//

void free_little_id(Little_Buddy * p,int k){

if(0==k){

#ifdef DEBUG

cout<<"root "<<endl;

#endif

return;

}

if(1==k){

#ifdef DEBUG

cout<<"little root freed "<<endl;

#endif

p->occupied[1]=FALSE;//清空索引所指向的空间

p->semi[1]=FALSE;//清空索引所指向的空间

return;

}

if(0==k%2){//左结点

#ifdef DEBUG1

cout<<k<<" left virutal freed"<<endl;

#endif

if(!p->occupied[k+1] || !p->semi[k+1]){//右边也空

#ifdef DEBUG1

cout<<k+1<<" right blank too"<<endl;

#endif

free_little_id(p,k/2);

p->occupied[k]=FALSE;//清空索引所指向的空间

p->semi[k]=FALSE;//清空索引所指向的空间

}

}

else{//是右结点

#ifdef DEBUG1

cout<<k<<" right virutal freed"<<endl;

#endif

if(!p->occupied[k-1]||!p->semi[k-1]){//左边也空

#ifdef DEBUG1

cout<<k-1<<"left blank too"<<endl;

#endif

free_little_id(p,(k-1)/2);

p->occupied[k]=FALSE;//清空索引所指向的空间

}

}

}//end free_little_id

//

//

void free_little(void * addr){

int target=(int)addr;

int d;

for(int d=0;d<BIG_BLOCK_MAX;d++){

int head=(int)lb_list[d];

int tail=(int)((char*)lb_list[d]+BIG_BLOCK_SIZE);

if(target>=head &&target<tail){

int k=target%LITTLE_BLOCK_MAX;

Little_Buddy * p=lb_list[d];

while(p->address[k]!=addr ||!p->occu_id[k]){

k++;

if(k==BIG_BLOCK_MAX){

k=0;

}

}

int id=p->occu_id[k];

p->occupied[id]=FALSE;

p->semi[id]=FALSE;

#ifdef DEBUG1

cout<<"idx"<<k<<endl<<endl;

#endif

if(id==1){//是小表根结点

free(p);//释放掉小表根

#ifdef DEBUG

cout<<"free little table"<<endl<<endl;

#endif

}

if(id%2==0){//左结点

if(!p->occupied[id+1] &&!p->semi[id+1]){//右边也空

#ifdef DEBUG

cout<<" right also blank:"<<id<<endl<<endl;

#endif

free_little_id(p,id/2);//释放上层结点

return;

}

}

else{//右结点

if(!p->occupied[p->occu_id[k]-1]){//左边也空

#ifdef DEBUG

cout<<"left also blank:"<<p->occu_id[k]<<endl<<endl;

#endif

free_little_id(p,(id-1)/2);//释放上层结点

return;

}

}

}

}

}

//

//

void free(void * addr){

int target=(int)addr;

int base=(int)SYS_STACK;

if(target<base ||target>base+STACK_MAX){return;}

if((target-base)% BIG_BLOCK_SIZE==0){//是大表上的结点,BIG_BLOCK_SIZE为单位分配

#ifdef DEBUG

cout<<"free_big"<<endl;

#endif

free_big(addr);

}

else{//小表

#ifdef DEBUG

cout<<"free_little"<<endl;

#endif

free_little(addr);

}

}

int memory_size(void * addr){ // chech that how many space has assign to it

int target=(int)addr;

int base=(int)SYS_STACK;

if(target<base ||target>base+STACK_MAX){return -1;}

if((target-base)% BIG_BLOCK_SIZE==0){//是大表上的结点,BIG_BLOCK_SIZE为单位分配

#ifdef DEBUG

cout<<"free_big"<<endl;

#endif

return memory_size_big(addr);

}

else{//小表

#ifdef DEBUG

cout<<"size_little"<<endl;

#endif

return memory_size_little(addr);

}

}

/*

*99 未知错误

98 空间不足

96 释放一个buddy系统中没有的地址(指针)

*

* */

#ifdef TEST_MEMORY

int main(){

double * d[10];

#ifdef TEST_BIG

int * a=(int*)malloc(1000*sizeof(int));

a[999]=1;

free(a);

double * d[10];

d[0]=(double *)malloc(2000*sizeof(double));

d[1]=(double *)malloc(2000*sizeof(double));

d[2]=(double *)malloc(4000*sizeof(double));

d[3]=(double *)malloc(8000*sizeof(double));

int i;

for(i=0;i<4;i++){

free(d[i]);

}

//d[0]=(double *)malloc(8000*sizeof(double));

d[1]=(double *)malloc(16000*sizeof(double));

//d[2]=(double *)malloc(4000*sizeof(double));

//d[3]=(double *)malloc(8000*sizeof(double));

d[1][15999]=1;

free(d[1]);

d[1]=(double *)malloc(32000*sizeof(double));

free(d[1]);

d[1]=(double *)malloc(42000*sizeof(double));

#endif

#ifdef TEST_LITTLE

d[0]=(double *)malloc(2);

d[1]=(double *)malloc(4);

d[2]=(double *)malloc(8);

d[3]=(double *)malloc(16);

d[4]=(double *)malloc(32);

d[5]=(double *)malloc(64);

int i;

for(i=0;i<6;i++){

free(d[i]);

}

#endif

}

#endif //endif TEST_MEMORY

#endif//endif MEMORY_C

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有