易码技术论坛

 找回密码
 加入易码
搜索
查看: 126038|回复: 7

[LAVA]动态内存分配与删除new和delete

[复制链接]
发表于 2005-1-25 12:20:00 | 显示全部楼层
实际占用的空间是  申请长度+4字节
不适宜生成长度较小而数量繁多的"数组",而且会增加delete的负担
发表于 2005-1-25 14:07:00 | 显示全部楼层
如非必要,可以把一些临时的数组写到局部变量中。这样过程结束的时候系统应该会释放这部分内存的。解释器的速度应该比Lava要快~~

不过,要是有特殊需要,这样也满好^_^
364_2831_152.gif
 楼主| 发表于 2005-1-25 22:10:00 | 显示全部楼层
呵呵,不好意思,小生总是把贴发错地方,有劳各位斑竹了!
发表于 2005-2-10 20:00:00 | 显示全部楼层
呵呵 ,好东西啊~哦哦!
发表于 2005-3-12 19:01:00 | 显示全部楼层
没仔细看代码
我有更简单的方法
我的方法:
此方法在函数返回的时候就能自动的delete,不过会通过不了lava 认证
具体方法:
在零页地址找到lava系统的程序环境指针(注意不是运算栈)寄存器(具体地址忘了 不好意思),把这个指针+上要申请的长度

然后返回原来的环境指针,用来访问。
其实就和8086汇编里sp ,bp那个东西差不多
不过这个方法有个大的缺陷 就是在返回之后才会释放空间 如果在一个子程序中申请太多的话~~ 就会overflow!
而且,可能会造成一些兼容性的问题
代码:
#define _BP 0xFFFF//需要按照实际改一下
int _r;
int foo(int len)
{
_r=*(_BP) && *(_BP+1)<<8;
len=len+_r;
*(_BP)=len&&0xFF;
*(_BP+1)=len>>8;
return _r;
}
发表于 2005-3-12 19:09:00 | 显示全部楼层
补充下

这个方法申请的空间有效期只限于调用foo函数 的函数返回之前,因为一旦返回就自动delete了

在某些情况下还算有用
发表于 2005-3-13 18:32:00 | 显示全部楼层
发现昨天的方法并不好,其实可以不需要直接访问BP(我以前叫环境指针,现在和8086汇编统一了),lava虚拟机会帮我们做这件事

int _new(int len)
{
    char _fill[0x100];//为了防止重建的返回信息覆盖_new_main的数据
    return _new_main(len);
}
int _new_main(int len)
{
    int _addressing[2]; //这里最小是2
   
    _addressing[0]=_addressing[-3];
    _addressing[-3]=_addressing[-3]+len;
    memmove(_addressing[-3],_addressing[0],5);//重建返回信息
    return _addressing[0];
}
代码没有调试 可能有错 时间不够了 如果有错改天再改
为什么要弄成两个函数呢? 答:因为一个实现不了。(众人:废话)
解释一下
预备知识:
在bp[0..2]的地方存放着返回地址
在bp[3..4]的地方存放着返回后的bp
在bp[5..5+i*4](i为参数个数)的地方存放着参数,每个参数一律4bytes
以后的地址依次存放定义的变量
开始的时候,bp指向0处,sp(其实应该叫nbp,就是下一个bp)指向1处
低地址>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>高地址
|数据|数据|数据|...|数据|数据 |0  调用_new的函数的数据 |1..(未用)

.调用_new后
bp指向1处,sp指向2处
|数据|数据|数据|...|数据|数据 |0  调用_new的函数的数据 |1  _new的数据 |2..(未用)
.调用_new_main后
bp指向2处,sp指向3处
|数据|数据|数据|...|数据|数据 |0  调用_new的函数的数据 |1  _new的数据 |2 _new_main的数据|3..(未用)
.这个时候 _new_main修改 bp处的返回后bp的值并重建返回信息(_new里的char _fill[0x100];保证重建的返回信息不会覆盖掉_new_main的返回信息),然后返回(关键步骤)
.返回_new后
bp指向1'处,sp指向2处
|数据|数据|数据|...|数据|数据 |0  调用_new的函数的数据 |1 (申请的空间) |1' 部分_new的数据 |2..(未用)
虽然现在已经不能正常访问数据了(bp被我们悄悄的修改了),但是现在只剩一步了,
就是返回一个值,然后return了,这一步并不访问任何变量,返回值一直都在运算栈中
.最后返回了
bp指向0处,sp指向1'处
|数据|数据|数据|...|数据|数据 |0  调用_new的函数的数据 |1 (申请的空间) |1'..(未用)
这样就申请了一块地方
另外,这个函数不能申请256字节附近大小的的空间,以防止覆盖掉new_main的返回信息,当然对于1-256以及300以上的大小就随意了
p.s. 上边说的缺点(这个方法申请的空间有效期只限于调用foo函数 的函数返回之前,因为一旦返回就自动delete了), 还存在,原理所致。但是,一般来说不会出现申请空间然后返回给调用者用的情况,可以在调用者那边就申请好 然后传参数给被调用者
 楼主| 发表于 2005-1-25 12:17:57 | 显示全部楼层 |阅读模式
其实早就研究出来了,可是考虑到~~可能不太稳定,最近测试了一下处理少量的数组还算速度~

#define _DEBUG 1


#define K_UP 20
#define K_DOWN 21
#define K_RIGHT 22
#define K_LEFT 23
#define K_ENTER 13
#define K_ESC 27
#define K_PAGEUP 19
#define K_PAGEDOWN 14
#define K_DEBUG 'd'

#define DYNAMIC_RAM_LEN 16384 //可以自己改,这值是我的引擎中设定的


char dynamic_ram[DYNAMIC_RAM_LEN];

int dynamic_len;

void hex(char c,int adr)
{
  int _a,_b;
  _a=c/16;
  _b=c%16;
  if(_a<10) _a=_a+48; else _a=_a+87;
  if(_b<10) _b=_b+48; else _b=_b+87;
  *adr=_a;*(adr+1)=_b;
}
void _debug()
{
  char s[5];
  long base;
  char _c;
  int _y,_x;
  memset(s,0,5);
  base=0x2000;
  SetScreen(1);
  for(;;)
  {
   for(_y=0;_y<6;_y++)
   {
    for(_x=0;_x<8;_x++)
    {
     hex(*(base+_y*8+_x),_TEXT+_x*2+_y*26);
     *(_TEXT+_x+16+_y*26)=*(base+_y*8+_x);
    }
   }
   UpdateLCD(0);
   _c=getchar();
   if(_c==K_UP) base=base-8;
   if(_c==K_DOWN) base=base+8;
   if(_c==K_LEFT) base=base-48;
   if(_c==K_RIGHT) base=base+48;
   if(_c==K_PAGEDOWN) base=base+256;
   if(_c==K_PAGEUP) base=base-256;
   if(_c=='i') base=base-4096;
   if(_c=='k') base=base+4096;
   if(_c==32) {hex(base/256,s);hex(base%256,s+2);TextOut(4,4,s,0x40);Box(3,4,28,14,0,1); getchar();}
  }
}
void error(int e,int class,int reason)
{
SetScreen(1);
printf("引擎出错:\n错误:%s\n  种类:%s\n原因:%s\n热键退出!",e,class,reason);
for(;;)
{
  if(getchar()==K_DEBUG&&_DEBUG==1) _debug();
}
}
/********/

void w_int(int p,int v)
{
if(p<0x19c0||p>0x7fff) error("写数据错误","非法地址","程序bug或资源文件错误");
*(p+1)=(v&0xff00)>>8;
*(p)=(v&0x00ff);
}

int _int(int p)
{
return (*(p+1)<<8)|*(p);
}

void new(int p,int len)
{
if(dynamic_len+len+4>DYNAMIC_RAM_LEN) error("动态分配内存","内存不足","程序规划错误或资源文件参数错误");
w_int(p,dynamic_len+dynamic_ram+4);
w_int(dynamic_len+dynamic_ram,p);
w_int(dynamic_len+dynamic_ram+2,len);
dynamic_len=dynamic_len+len+4;
}

void delete(int p)
{
int len;
int i;
if(_int(p)==0) return;
if(_int(p)<dynamic_ram||_int(p)>=dynamic_ram+DYNAMIC_RAM_LEN) error("动态删除内存","指针范围出错","程序规划错误.");
if(_int(_int(p)-4)!=p) error("动态删除内存","指针校验出错","程序归划错误");
len=_int(_int(p)-2);
i=_int(p)-4;
i=i+_int(i+2)+4;
while(i!=dynamic_len+dynamic_ram)
{
  w_int(_int(i),_int(_int(i))-4-len);
  i=i+_int(i+2)+4;
}
memcpy(_int(p)-4,_int(p)+len,DYNAMIC_RAM_LEN-_int(p)-len);
dynamic_len=dynamic_len-len-4;
w_int(p,0);
}
/********/


使用是需要先将指针定义为全局变量或是main中的变量

使用new的方法:new(&指针,数组长度);

这时指针会指像分配好的内存地址上

使用delete的方法:delete(&指针);

这时会删除指针所值的内存地址并将指针的值改为0,但不清0数据区的数据

delete删除未事先定义的指针时会报错!
您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2025-6-15 03:01 , Processed in 0.016892 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表