"Subscript Out of Range" for Array > 128K; Gaps in Far Heap
ID: Q26494
|
The information in this article applies to:
-
Microsoft Visual Basic Standard and Professional Editions for MS-DOS, version 1.0
-
Microsoft QuickBASIC for MS-DOS, versions 4.0, 4.0b, 4.5
-
Microsoft BASIC Professional Development System (PDS) for MS-DOS, versions 7.0, 7.1
-
Microsoft BASIC Compiler for MS-DOS and MS OS/2, versions 6.0, 6.0b
SUMMARY
The program listed below when compiled with the /ah option (in
VBDOS.EXE or BC.EXE) to support a huge (larger than 64K) array,
produces a "Subscript out of range" error message for an array larger
than 128K, even though the FRE(-1) function indicates that there
should be enough available memory.
To make an array larger than 128K and avoid the "Subscript out of
range" error message, the number of bytes in each element of the huge
array must be a power of 2 (that is, evenly divisible into 64K), as
explained below.
This information is also included with the Help file provided with
the Standard and Professional Editions of Microsoft Visual Basic
for MS-DOS, version 1.0.
MORE INFORMATION
Space is allocated for a huge array contiguously in far heap, with the
restriction that no single array element (or record) is allowed to be
split across a 64K boundary. If a record size is not a power of 2,
then Basic allocates the first array element at an offset high enough,
relative to the array's base segment address (returned by the VARSEG
function), such that no array element is split across the boundary at
exactly 64K above the base segment. (This creates a gap in the far
heap.) The value returned by the VARPTR function for the first element
of the array then indicates both the offset of the array, and also
the size of a gap created in the far heap. The size of the gap is also
equal to (65,536) MOD (array record size). This gap fragments far heap,
and is wasted, unused memory. In the worst case, the gap can be up to
(array record size) minus 1 in size.
A "Subscript out of range" error occurs when allocating a huge array
larger than 128K if the array elements have a size that is not an even
power of 2. Arrays larger than 128K must have an element (or record)
size that is a power of 2 (2, 4, 8, 16, 32, 64, etc.), since arrays
must be stored contiguously and no single array element is allowed to
span across a 64K boundary.
You can compensate for this limitation by padding each array element
to a size that can be evenly divided into 64K (that is, a power of 2,
such as 4, 8, 16, 32, 64, 128, or 512 bytes), as shown in the example
below.
A huge array must be DIMensioned as a dynamic array, either with a
variable in the array subscript or with the preceding metacommand REM
$DYNAMIC. The /AH option allows dynamic arrays of user-defined types,
fixed-length strings, and numeric data to occupy all of available
memory.
The following example shows how to work around the "Subscript out of
range" error message:
' To try this example in VBDOS.EXE:
' 1. From the File menu, choose New Project.
' 2. Copy the code example to the Code window.
' 3. Press F5 to run the program.
DEFINT A-Z
TYPE test
a AS DOUBLE ' 8 bytes.
b AS STRING * 288 ' 288 bytes.
PAD AS STRING * 216 ' Must pad to make 512-byte total record size
END TYPE
max = 453
REM $DYNAMIC
DIM x(1 TO max) AS test
END
The following code example demonstrates the "Subscript out of range"
error message:
' To try this example in VBDOS.EXE:
' 1. From the File menu, choose New Project.
' 2. Copy the code example to the Code window.
' 3. Press F5 to run the program.
DEFINT A-Z
TYPE test
a AS DOUBLE ' Uses 8 bytes.
b AS STRING * 288 ' Uses 288 bytes.
END TYPE
max = 453
REM $DYNAMIC
PRINT FRE(-1) ' Prints free heap space.
DIM x(1 TO max) AS test ' 453 * (288 + 8) = 134088 bytes used
PRINT FRE(-1),"AFTER DIM"
END
Additional query words:
VBmsdos QuickBas BasicCom
Keywords :
Version : MS-DOS:1.0,4.0,4.0b,4.5; :6.0,6.0b,7.0,7.1
Platform : MS-DOS
Issue type :