Microsoft KB Archive/101880: Difference between revisions

From BetaArchive Wiki
(importing KB archive)
 
m (Text replacement - """ to """)
Line 65: Line 65:
=== Diagnosing Near Heap Depletion ===
=== Diagnosing Near Heap Depletion ===


The error "Out of memory" happens when you run out of either near heap or far heap space. Usually, you run out of near heap space. Determine which area is depleted by printing out the amount of free space in each area as shown below:
The error "Out of memory" happens when you run out of either near heap or far heap space. Usually, you run out of near heap space. Determine which area is depleted by printing out the amount of free space in each area as shown below:
<pre class="codesample">  ' show number of free bytes far heap:
<pre class="codesample">  ' show number of free bytes far heap:
   PRINT FRE(-1)
   PRINT FRE(-1)
Line 72: Line 72:
   PRINT FRE(0)  ' for QuickBasic
   PRINT FRE(0)  ' for QuickBasic
                 </pre>
                 </pre>
If you find that you have the same amount of free hear and far heap space, far heap is depleted. You should print these values as near as possible to the point in your program immediately before the &quot;Out of memory&quot; error occurs.
If you find that you have the same amount of free hear and far heap space, far heap is depleted. You should print these values as near as possible to the point in your program immediately before the "Out of memory" error occurs.
=== Increasing Free Near Heap ===
=== Increasing Free Near Heap ===


Line 88: Line 88:
                 </pre>
                 </pre>
Use the RTRIM$ function to remove trailing spaces from fixed-length strings when you retrieve them from the array. For example
Use the RTRIM$ function to remove trailing spaces from fixed-length strings when you retrieve them from the array. For example
<pre class="codesample">  a$(1) = &quot;hello&quot;
<pre class="codesample">  a$(1) = "hello"
   PRINT &quot;&lt;&quot; + a$(1) + &quot;&gt;&quot;         ' prints &lt;hello&gt;
   PRINT "&lt;" + a$(1) + "&gt;"         ' prints &lt;hello&gt;
   c(1) = &quot;hello&quot;
   c(1) = "hello"
   PRINT &quot;&lt;&quot; + c(1) + &quot;&gt;&quot;           ' prints &lt;hello  &gt;
   PRINT "&lt;" + c(1) + "&gt;"           ' prints &lt;hello  &gt;
   PRINT &quot;&lt;&quot; + RTRIM$(c(1)) + &quot;&gt;&quot;   ' prints &lt;hello&gt;
   PRINT "&lt;" + RTRIM$(c(1)) + "&gt;"   ' prints &lt;hello&gt;
                 </pre>
                 </pre>
Using fixed-length arrays typically increases the storage required for each string because space is reserved for the maximum possible length. If you require an array larger than 64K, invoke the interpreter or compiler with the /Ah option. Otherwise you receive &quot;Subscript out of range,&quot; error 9.
Using fixed-length arrays typically increases the storage required for each string because space is reserved for the maximum possible length. If you require an array larger than 64K, invoke the interpreter or compiler with the /Ah option. Otherwise you receive "Subscript out of range," error 9.
<div class="indent">
<div class="indent">


Line 104: Line 104:


</div>
</div>
If you require an array larger than 128K, specify the length for each string in the array as a power of 2 (2, 4, 8, 16, 32, and so on). otherwise you receive the error &quot;Subscript out of range.&quot;
If you require an array larger than 128K, specify the length for each string in the array as a power of 2 (2, 4, 8, 16, 32, and so on). otherwise you receive the error "Subscript out of range."
<pre class="codesample">  DIM a(8000) AS STRING * 17  ' causes error &quot;Subscript out of range&quot;
<pre class="codesample">  DIM a(8000) AS STRING * 17  ' causes error "Subscript out of range"
   DIM b(8000) AS STRING * 16  ' okay
   DIM b(8000) AS STRING * 16  ' okay
                 </pre>
                 </pre>
Line 114: Line 114:
   END TYPE
   END TYPE
   DIM t1 AS aType              ' stored in near heap
   DIM t1 AS aType              ' stored in near heap
   t1.s = &quot;hello&quot;
   t1.s = "hello"
   PRINT t1.s
   PRINT t1.s
   DIM t2(0) AS aType          ' stored in far heap
   DIM t2(0) AS aType          ' stored in far heap
   t2(0).s = &quot;hello&quot;
   t2(0).s = "hello"
   PRINT t2(0).s
   PRINT t2(0).s


Line 123: Line 123:
   DIM f2(0) AS STRING * 2000  ' stored in far heap
   DIM f2(0) AS STRING * 2000  ' stored in far heap
                 </pre>
                 </pre>
After adding REM $DYNAMIC to a support module (a .BAS file other than your start-up file), you may encounter a side effect problem with the symptom of error &quot;Subscript out of range.&quot; This happens on arrays defined with DIM SHARED at the module level of a support module. Similarly, after adding REM $DYNAMIC to a form, you may encounter the error &quot;Executable code not allowed in module level of a form.&quot; These errors are due to REM $DYNAMIC changing DIM SHARED from a compile-time statement to a run-time statement for arrays.<br />
After adding REM $DYNAMIC to a support module (a .BAS file other than your start-up file), you may encounter a side effect problem with the symptom of error "Subscript out of range." This happens on arrays defined with DIM SHARED at the module level of a support module. Similarly, after adding REM $DYNAMIC to a form, you may encounter the error "Executable code not allowed in module level of a form." These errors are due to REM $DYNAMIC changing DIM SHARED from a compile-time statement to a run-time statement for arrays.<br />
<br />
<br />
To work around the &quot;Subscript out of range&quot; side effect problem, define the array at the module level and allocate the array in a SUB or FUNCTION. Use a STATIC variable to keep track of whether the array has been allocated. For example:
To work around the "Subscript out of range" side effect problem, define the array at the module level and allocate the array in a SUB or FUNCTION. Use a STATIC variable to keep track of whether the array has been allocated. For example:
<pre class="codesample">    REM $DYNAMIC
<pre class="codesample">    REM $DYNAMIC
   DIM SHARED b() AS INTEGER
   DIM SHARED b() AS INTEGER
Line 140: Line 140:
   END SUB
   END SUB
                 </pre>
                 </pre>
To work around the Visual Basic error &quot;Executable code not allowed in module level of a form,&quot; define the array at the module level and use REDIM to allocate the array from the Form_Load event handler.
To work around the Visual Basic error "Executable code not allowed in module level of a form," define the array at the module level and use REDIM to allocate the array from the Form_Load event handler.


</div>
</div>

Revision as of 09:22, 20 July 2020

Article ID: 101880

Article Last Modified on 8/16/2005



APPLIES TO

  • Microsoft Visual Basic for MS-DOS
  • Microsoft BASIC Professional Development System 7.0
  • Microsoft BASIC Professional Development System 7.1
  • Microsoft QuickBasic 4.0
  • Microsoft QuickBASIC 4.0b
  • Microsoft QuickBasic 4.5 for MS-DOS



This article was previously published under Q101880

SUMMARY

This article gives suggestions on how to work around the following errors:

Out of memory (code 7)
Stack plus data exceed 64K (L2041)

These suggestions apply to both interpreted and compiled programs.

MORE INFORMATION

Diagnosing Near Heap Depletion

The error "Out of memory" happens when you run out of either near heap or far heap space. Usually, you run out of near heap space. Determine which area is depleted by printing out the amount of free space in each area as shown below:

   ' show number of free bytes far heap:
   PRINT FRE(-1)
   ' show number of free bytes near heap:
   PRINT STACK    ' for VB-DOS and Basic PDS
   PRINT FRE(0)   ' for QuickBasic
                

If you find that you have the same amount of free hear and far heap space, far heap is depleted. You should print these values as near as possible to the point in your program immediately before the "Out of memory" error occurs.

Increasing Free Near Heap

Add the REM $DYNAMIC (or '$DYNAMIC) statement to the top of each module and form. This statement allows you to change the number of elements in your arrays at run time (by using REDIM). Even more important, the statement causes the arrays to store in far heap rather than near heap. Arrays of variable-length strings are an exception; they are always in the near heap whether or not they are dynamic.

   DIM a(1000) AS INTEGER  ' static array, stored in near heap
   REM $DYNAMIC
   DIM b(1000) AS INTEGER  ' dynamic array, stored in far heap
                

Convert arrays of variable-length strings into arrays of fixed-length strings to allow REM $DYNAMIC to store this data in far heap. For example:

   ' example arrays of variable-length strings
   DIM a$(2000)
   DIM b(2000) AS STRING
   ' example array of fixed-length strings, up to length 16 each
   DIM c(2000) AS STRING * 16
                

Use the RTRIM$ function to remove trailing spaces from fixed-length strings when you retrieve them from the array. For example

   a$(1) = "hello"
   PRINT "<" + a$(1) + ">"          ' prints <hello>
   c(1) = "hello"
   PRINT "<" + c(1) + ">"           ' prints <hello   >
   PRINT "<" + RTRIM$(c(1)) + ">"   ' prints <hello>
                

Using fixed-length arrays typically increases the storage required for each string because space is reserved for the maximum possible length. If you require an array larger than 64K, invoke the interpreter or compiler with the /Ah option. Otherwise you receive "Subscript out of range," error 9.

VBDOS /Ah -- Visual Basic for MS-DOS
QBX /Ah -- Basic PDS
QB /Ah -- Microsoft QuickBasic
BC /Ah ... -- compiler for all 3 products


If you require an array larger than 128K, specify the length for each string in the array as a power of 2 (2, 4, 8, 16, 32, and so on). otherwise you receive the error "Subscript out of range."

   DIM a(8000) AS STRING * 17  ' causes error "Subscript out of range"
   DIM b(8000) AS STRING * 16  ' okay
                

Create arrays of one element out of large variables that are not already arrays and are not variable-length strings. This causes REM $DYNAMIC to store them in far heap rather than near heap. User defined type variables and fixed-length strings are good candidates. For example,

    TYPE aType
      s AS STRING * 1000
      a(100) AS LONG
   END TYPE
   DIM t1 AS aType              ' stored in near heap
   t1.s = "hello"
   PRINT t1.s
   DIM t2(0) AS aType           ' stored in far heap
   t2(0).s = "hello"
   PRINT t2(0).s

   DIM f1 AS STRING * 2000      ' stored in near heap
   DIM f2(0) AS STRING * 2000   ' stored in far heap
                

After adding REM $DYNAMIC to a support module (a .BAS file other than your start-up file), you may encounter a side effect problem with the symptom of error "Subscript out of range." This happens on arrays defined with DIM SHARED at the module level of a support module. Similarly, after adding REM $DYNAMIC to a form, you may encounter the error "Executable code not allowed in module level of a form." These errors are due to REM $DYNAMIC changing DIM SHARED from a compile-time statement to a run-time statement for arrays.

To work around the "Subscript out of range" side effect problem, define the array at the module level and allocate the array in a SUB or FUNCTION. Use a STATIC variable to keep track of whether the array has been allocated. For example:

    REM $DYNAMIC
   DIM SHARED b() AS INTEGER

   SUB s ()
      STATIC is_alloc AS INTEGER
      IF NOT is_alloc THEN
         DIM b(1000) AS INTEGER
         is_alloc = -1  ' true
      END IF

      b(100) = 123
      PRINT b(100)
   END SUB
                

To work around the Visual Basic error "Executable code not allowed in module level of a form," define the array at the module level and use REDIM to allocate the array from the Form_Load event handler.


Additional query words: VBmsdos QuickBas BasicCom B_VBmsdos 1.00 b_basiccom 7.10 b_quickbas 4.50

Keywords: KB101880