Bad EXE Result, Expression Indexing Dynamic Long Integer Array (59428)






This article was previously published under Q59428

SYMPTOMS

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.

STATUS

Microsoft has confirmed this to be a bug 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).

MORE INFORMATION

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%
				

Modification Type: Minor Last Reviewed: 1/9/2003
Keywords: KB59428