Delphi中动态数组的最大长度?

时间:2009-06-12 04:34:46

标签: delphi delphi-2009

我很好奇动态数组有多长,所以我试过

SetLength(dynArray, High(Int64));

它的值为9,223,372,036,854,775,807,我认为这是我可以参考的最大索引数。它给了我一个:

  

ERangeError,消息为“范围检查错误”。

所以我试过了:

SetLength(dynArray, MaxInt); 

并得到了同样的错误!

有趣的是我可以用

来调用它
SetLength(dynArray, Trunc(Power(2, 32));

实际上是MaxInt大小的两倍!

我试过

SetLength(dynArray, Trunc(Power(2, 63) - 1));

与High(Int64)相同,但也失败了。

没有继续尝试和错误,有人知道最大尺寸吗?它取决于数组中元素的大小吗?

我正在使用Delphi 2009.不同版本会有所不同(很明显,当Commadore推出时它应该更大!)

4 个答案:

答案 0 :(得分:18)

从第20628行的System.DynArraySetLength过程可以清楚地看出答案:

Inc(neededSize, Sizeof(Longint)*2);
if neededSize < 0 then
  Error(reRangeError);

因此,理论上Maxint - SizeOf(Longint)* 2.你可以分配的最大值而不会引发范围检查错误。实际上,根据可用的内存量,你会得到一个内存不足的错误。

答案 1 :(得分:5)

没有必要推测动态阵列的最大理论长度,因为最大实际长度要小得多。

数据结构的大小及其中包含的数据必须小于应用程序可以分配的最大内存,减去应用程序代码本身,堆栈和其他数据所需的内存。在Windows上(32位,我们现在唯一可以用Delphi定位的版本)这是一个2 GByte或3 GByte的虚拟地址范围,每个应用程序都有一个用于OS加载程序的特殊开关。我不确定Delphi应用程序是否可以处理3 GB内存空间,因为在使用整数而不是LongWords的所有地方,最后三分之一的偏移值都会有负值。

因此,您可以尝试分配一个80%或90%MaxInt div SizeOf(array element)的动态数组 - 最可能的结果是该内存块的分配在运行时失败。

另外:给出int64长度并且没有异常并不意味着数组具有预期的长度。请考虑以下代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  a: array of byte;
  l: int64;
begin
  l := $4000000000;
  SetLength(a, l);
  Caption := IntToStr(Length(a));
end;

如果范围检查已关闭,则无需提示和警告即可编译,并且无异常运行。在调用 SetLength()之后,只有一个小问题是数组的长度为0。因此,对于您的问题中的检查,您应该在成功的 SetLength()之后回读动态数组的长度,这是确保编译器和运行时完成您的预期的唯一方法。

答案 2 :(得分:1)

请注意,afaik elementcount也是有限的,不太可能超过2 ^ 31-1。可能是该大小具有相同的限制(以避免在RTL中签名的&lt;&gt;无符号问题)我怀疑即使在/ 3GB模式下也可能超过2GB。

答案 3 :(得分:1)

MMaths:

  

max_array_bytesize = 2 ^ 31 - 9

     

max_array_elements_number = [(2 ^ 31 - 9)/ array_element_bytesize]

代码:

max_array_elements_number := (MaxInt-Sizeof(Longint)*2) div SizeOf(array_element);

示例:

type
  TFoo = <type_description>;
  TFooDynArray = array of TFoo
const
  cMaxMemBuffSize = MaxInt-Sizeof(Longint)*2;
var
  A : TFooDynArray;
  B : array of int64;
  MaxElems_A : integer;
  MaxElems_B : integer;
begin
  MaxElems_A := cMaxMemBuffSize div SizeOf(TFoo);
  MaxElems_B := cMaxMemBuffSize div SizeOf(int64);

  ShowMessage('Max elements number for array:'#13#10+
              '1) A is '+IntToStr(MaxElems_A)+#13#10+
              '2) B is '+IntToStr(MaxElems_B)
              );
end;