Tutorial :Max length for a dynamic array in Delphi?


I was curious how long a dynamic array could be so I tried

SetLength(dynArray, High(Int64));  

That has a value of 9,223,372,036,854,775,807 and I figure that would be the largest number of indexes I could reference anyway. It gave me a:

ERangeError with message 'Range check error'.

So I tried:

SetLength(dynArray, MaxInt);   

and got the same error!

Interestingly I could call it with

SetLength(dynArray, Trunc(Power(2, 32));  

Which is actually twice the size of MaxInt!

I tried

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

Which is the same as High(Int64), and that failed too.

Short of continued trial and error, does someone know the maximum size? Does it depend on the size of the elements in the array?

I am using Delphi 2009. Will it be different for different versions (obviously when Commadore comes out it should be greater!)


The answer is clear from System.DynArraySetLength procedure, from line 20628:

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

The maximum value you can allocate without raising a range check error is therefore theoretically Maxint - SizeOf(Longint) * 2. Practically, you will get an out-of-memory error depending on how much memory is available.


There's no point in speculating about the maximum theoretical length of a dynamic array, as the maximum practical length is much smaller.

The size of the data structure and the data contained in it has to be smaller than the maximum memory an application can allocate, minus the memory the application code itself, the stack and the other data will need. On Windows (32 bit, the only version we mere mortals can target with Delphi right now) this is a virtual address range of 2 GByte, or 3 GByte with a special switch for the OS loader, for each application. I'm not sure though that a Delphi application can even handle the 3 GByte memory space, as the last third would have negative values for offsets in all places where integers are used instead of LongWords.

So you could try to allocate a dynamic array of say 80% or 90% of MaxInt div SizeOf(array element) - with the most probable result that the allocation of that memory block fails at runtime.

Also: giving an int64 length and getting no exception would not mean that the array has the intended length. Consider this code:

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

If range checking is off this will compile without hints and warnings, and run without exceptions. It has only the slight problem that the array has length 0 after the call to SetLength(). So for the checks in your question you should definitely read back the length of the dynamic array after a successful SetLength(), it is the only way to be sure that the compiler and runtime did what you intended.


Note that afaik elementcount is also limited, more than 2^31-1 is unlikely. It could be that size has the same limit (to avoid signed<>unsigned issues in the RTL) I doubt that more of than 2GB is possible even in /3GB mode.



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;  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Next Post »