关于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;
应该就可以了