关于SetLength报Out of memory的研究及解决办法



最近在做一个GIS系统, 在读GIS数据时采用了动态数组,突然读一个数据时SetLength报错!Out of memory



仔细研究了代码, 发现代码没有问题。问题应该动态数组的问题。



接下来查看各种资料,发现也有一些人发现了类似的问题,一般认为是频繁SetLength造成的,

具体为什么为造成错误呢?

我们来做一个测试



procedure TForm1.Button1Click(Sender: TObject);

var

     I,J  : Integer;

begin

     for I := 1 to 10 do  begin

          SetLength(giDatas,I*10);

          giDatas[I*10-1]   := I;

          //

          Memo1.Lines.Add(Format('I=%.2d, Addr = %d',[I,Integer(@giDatas[0])]));

     end;

end;



这个一段非常简单的代码,一般会认为@giDatas[0]会是定值(至少我以前是这样认为的)



I=01, Addr = 27139384

I=02, Addr = 26525640

I=03, Addr = 26525640

I=04, Addr = 26395448

I=05, Addr = 26395448

I=06, Addr = 26395448

I=07, Addr = 26395448

I=08, Addr = 26694280

I=09, Addr = 26694280

I=10, Addr = 26694280



根据得出的结果来看,@giDatas[0]在不断改变, 也就是giDatas在不断开辟新的内存

原来占用的内存没有及时释放,所以多次SetLength后会报Out of memory. 



问题找出来了, 解决办法还是问题。 仍然查找了许多资料, 发现用指针来解决

比如类似的程序

type

  duilie=record

     item_name:integer;

     level:integer;

     count:integer;

     father:integer;

     children:array of integer;

  end;

var 

  leaf:array of duilie;



其中leaf的定义采用

type

     Pduilie = ^duilie;

var

    leaf:array of pduilie; 

应该就可以了