KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q59428: Bad EXE Result, Expression Indexing Dynamic Long Integer Array

Article: Q59428
Product(s): See article
Version(s): 4.00 4.00b 4.50
Operating System(s): MS-DOS
Keyword(s): ENDUSER | B_BasicCom buglist4.00 buglist4.00b buglist4.50 | mspl13_basic
Last Modified: 4-SEP-1990

Subscripting $DYNAMIC long-integer arrays with expressions can give
incorrect results in a compiled .EXE program, as shown in the code
example further below. (The example below works correctly when run in
the QB.EXE editor.)

To work around this problem, do not use an expression in the
subscript. Instead, store the result of the expression in a temporary
variable and use that variable to subscript the array.

Microsoft has confirmed this to be a problem in Microsoft QuickBASIC
versions 4.00, 4.00b, and 4.50, and in Microsoft BASIC Compiler
versions 6.00 and 6.00b for MS-DOS and MS OS/2 (buglist6.00,
buglist6.00b). This problem was corrected in Microsoft BASIC
Professional Development System (PDS) version 7.00 (fixlist7.00).

Technical Note
--------------

You can view the cause of this problem by examining the assembly code
generated by your program. To do this, generate an assembly listing or
use Microsoft CodeView. This problem occurs because of an error in the
way that the array is referenced. Since the array is $DYNAMIC, the
address is a far address and should be referenced with ES:[BX] and
ES:[BX+02]. Instead, the array is referenced with [SI] and [SI+2].
This is not the correct address for the array and will yield incorrect
results.

Without the $DYNAMIC metacommand, the specific code below works
correctly, but a related example can cause the "Internal Error Near
xxxx" compiler error. A separate article, which describes the
circumstances for that error, can be found by querying on the
following words:

   internal and error and long and integer and array and subtraction
   and division

Code Example
------------

' LONGINT.BAS
' The following code example prints incorrect results when compiled and
' linked as specified:
'
'    Compile line: BC /D LONGINT;
'    LINK line:    LINK LONGINT;
'
'NOTE: The behavior of this program varies, depending on which BC
'      compile options (/O, /D, etc.) are used. Most combinations of
'      compiler options result in problems for this program. The problem
'      does not occur if you compile the example below with BC /O,
'      but similar examples give a problem even when compiled with /O.
'      The surest workaround, which works for all compiler options, is
'      to use temporary variables as shown below.
REM $DYNAMIC
DIM X&(1, 1)
' Note that a FOR...NEXT loop index variable (j%) is required to show
' the problem:
FOR j% = 1 TO 1
   ' The heart of the problem lies in lines A and B (marked below).
   ' You can partially solve the problem by modifying lines A and B
   ' in either one of the following two ways:
   '
   ' 1. Remove either line A or line B (corrects the problem in the
        remaining line B or A).
   ' 2. Reverse the order of lines A and B (corrects the problem in
   '    line A but moves the problem to line B).

   ' To completely solve the problem, you must use temporary
   ' (intermediate) variables (X1& and X2&) as shown in the following
   ' comments:
   '
   '  WORKAROUND: Add the next 4 lines, and remove lines A and B:
   '    X1& = X&(j%, 1 - j%)    ' Assign to temporary variable X1&.
   '    X2& = X&(j%, 2 - j%)    ' Assign to temporary variable X2&.
   '    Fail& = X1& + X2&       ' Use the temporary variables.
   '    Work& = X2& + X1&       ' Use the temporary variables.

' The heart of the problem lies in the following lines, marked A and B:
   Fail& = X&(j%, 1 - j%) + X&(j%, 2 - j%)   ' Consider this as line A
   Work& = X&(j%, 2 - j%) + X&(j%, 1 - j%)   ' Consider this as line B
   PRINT "Fail=", Fail&, "Work=", Work&      'Should print two 0's, but
                                             'Fail& gives garbage.
NEXT j%

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.