- 注册时间
- 2004-12-25
- 最后登录
- 1970-1-1
|
以前发过一个贴可以改变函数的内存大小,但是没有真正实现内存的动态使用.
但是这次不同了.
下面的程序以操作LavaX中额外的内存的方法实现了内存的动态分配,
对于程序的书写,以易读为主,没有针对速度做什么优化.
程序中各函数功能:
getsize,返回对应内存块的大小
arrangeram,整理内存,清理未使用的内存块
free,释放内存块,基本上只是将内存块标记为未使用
malloc,分配内存块
以下是程序代码:
/*
RAM:
0x2000:
[变量/函数头 内存]
.
.
.
[动态RAM]
*/
/*
动态RAM:
┏━ListEnd ┏>> NULL
┃ ┗━┓
┃ [空闲内存] ┃
┗> [next ]━┛<┓
┏━[last ] ┏━┛
┃ [used = F] ┃
┃ [size ] ┃
┃ [used ram] ┃
┃ ┃
┃ [已用内存] ┃
┗> [next ]━┛<┓
┏━[last ] ┏━┛
┃ [used = T] ┃
┃ [size ] ┃
┃ [used ram] ┃
┃ ┃
┃ [空闲内存] ┃
┗> [next ]━┛<┓
┏━[last ] ┏━┛
┃ [used = F] ┃
┃ [size ] ┃
┃ [used ram] ┃
┃ ┃
┃ ListHead━━┛
┗>ADD_MAX
*/
#define ADD_MAX 0x7fff //解释器能使用的最大内存地址
int ListHead = ADD_MAX;
int ListEnd = ADD_MAX;
struct INFO
{
int next; //下一块内存地址
int last; //上一块内存地址
int pointadd;//被返回指针的地址
char used; //是否空闲
int size; //大小
};
long getsize( long point) //取得内存块的大小
//point:指针
{
struct INFO &info;
&info = point - sizeof( struct INFO);
return info.size;
}
void arrangeram() //整理内存
{
int maxadd;
int pointadd;
int next;
struct INFO &info;
struct INFO &lastornext;
maxadd = ADD_MAX;
if( ListHead != ListEnd)//说明已有开辟的内存
{
&info = ListHead;
while( &info)
{
next = info.next;
if( info.used) //如果内存块已使用则移动到新地址,否则忽略
{
pointadd = info.pointadd;
(int *)pointadd = maxadd - info.size;
&lastornext = maxadd;
info.last = maxadd;
if( maxadd == ADD_MAX)
{
ListHead = ( maxadd = maxadd - info.size - sizeof( struct INFO));
}
else
{
maxadd = maxadd - info.size - sizeof( struct INFO);
lastornext.next = maxadd;
}
memmove( maxadd, &info, info.size + sizeof( struct INFO));
}
&info = next;
}
&info = maxadd;
info.next = 0;
}
ListEnd = maxadd;
}
void free( addr point) //释放内存(一般情况下只是标记为'未使用')
{
struct INFO &info;
struct INFO &lastornext;
&info = point - sizeof( struct INFO);
if( info.next == NULL)//判断是否为最后一块内存
{
//清除内存块节点
//重置链表尾信息
ListEnd = info.last;
//重置链表尾
&lastornext = ListEnd;
lastornext.next = NULL;
}
else
{
info.used = FALSE;
}
//arrangeram();//这里可以一释放就整理内存
}
addr malloc( long R_SIZE, long pointadd)//分配内存,返回被分配的内存地址
//R_size:要分配的内存大小(实际要比R_SIZE大一点)
//pointadd:被分配内存返回的地址所要保存的指针地址
{
int lastadd; //暂存一下地址
struct INFO &info;
struct INFO &lastornext;
char test;
//寻找现有空闲内存
if( ListHead != ListEnd) //说明有已开辟的内存
{
&info = ListHead;
while( &info)
{
if( info.used == FALSE && info.size >= R_SIZE)
{
//未使用的内存块,且容量足够,多出的空间被设置为新的空闲内存
if( info.size - R_SIZE > sizeof( struct INFO)) //有足够的多余空间设置新的空闲内存
{
//添加节点
lastadd = &info + R_SIZE + sizeof( struct INFO);
if( info.last != ADD_MAX)
{
&lastornext = info.last;
lastornext.next = lastadd;
ListHead = lastadd;
}
&lastornext = lastadd;
lastornext.next = &info;
lastornext.last = info.last;
info.last = lastadd;
//设置信息
info.size = R_SIZE;
lastornext.size = info.size - R_SIZE - sizeof( struct INFO);
lastornext.used = FALSE;
}
info.pointadd = pointadd;
info.used = TRUE;
return &info + sizeof( struct INFO);
}
&info = info.next;
}
}
//开辟新内存
if( &test + R_SIZE + sizeof( struct INFO) >= ListEnd)
{
arrangeram(); //自动整理内存
if( &test + R_SIZE + sizeof( struct INFO) >= ListEnd)
{
printf("内存不足!");
getchar();
exit(0);
}
}
//保留上一个内存块的地址
lastadd = ListEnd;
if( ListEnd < ADD_MAX)
{
//修改上一个内存块的next地址
&lastornext = ListEnd;
lastornext.next = ListEnd - R_SIZE - sizeof( struct INFO);
//修改内存使用的最大位置
ListEnd = lastornext.next;
}
else
{
ListEnd = ListEnd - R_SIZE - sizeof( struct INFO);
}
//取得内存块信息的地址
&info = ListEnd;
//记录上一个内存块的地址
info.last = lastadd;
//表示链表结尾
info.next = NULL;
//记录内存块大小信息
info.size = R_SIZE;
//标记已经在使用
info.used = TRUE;
//记录存放指针值的地址
info.pointadd = pointadd;
if( info.last == ADD_MAX)
{
ListHead = ListEnd;
}
(int *)pointadd = &info + sizeof( struct INFO);
return &info + sizeof( struct INFO);
}
void main(){
int a,b;
SetScreen(1);
printf("分配后:\n");
malloc(0x1000, &a);
malloc(0x2000, &b);
printf("a = %d,size = %d\n",a,getsize(a));
printf("b = %d,size = %d\n",b,getsize(b));
free(a);
malloc(0x800, &a);
arrangeram();
printf("释放a,分配a,整理后:\n");
printf("a = %d,size = %d\n",a,getsize(a));
printf("b = %d,size = %d",b,getsize(b));
}
真是晕!
似乎字宽总是有问题,编辑了N次也不行,凑合着看吧~~ |
|