KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q42595: VARSEG Incorrect for COMMON String Array Passed Through CHAIN

Article: Q42595
Product(s): See article
Version(s): 4.50
Operating System(s): MS-DOS
Keyword(s): ENDUSER | B_BasicCom buglist4.50 | mspl13_basic
Last Modified: 7-FEB-1990

The programs shown below demonstrate that VARSEG does not return the
correct segment address of a string array passed in a COMMON block
through a CHAIN.

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

The following program is TEST.BAS, which dimensions the string array
and passes it in COMMON:

   COMMON a$()
   DIM a$(4)
   CHAIN "test2"
   END

The following separately compiled program is TEST2.BAS, which
dimensions another string array and passes both to the C routine. The
second string array is used for comparison.

   DECLARE SUB crot CDECL (BYVAL plo AS INTEGER, BYVAL pls AS INTEGER)
   COMMON a$()
   DIM b$(1)
   a$(0) = "a0" + chr$(0)
   b$(0) = "b0" + chr$(0)
   print varseg(a$(0))
   print varseg(b$(0))
   CALL crot(VARPTR(a$(0)), VARSEG(a$(0)))
   CALL crot(VARPTR(b$(0)), VARSEG(b$(0)))

The following is the C routine CR.C, which should print out the first
string in each array:

   #include <stdio.h>
   struct struct_string {
       int length;
       char *address;
                        };
    void crot(struct struct_string far *string)
    {
         printf("%s\n", string->address);
    }

To demonstrate the problem from .EXE programs, compile and link as
follows:

     BC TEST.BAS ;
     LINK TEST.OBJ ;

     BC TEST2.BAS ;

     CL /AM /c CR.C ;

     LINK /NOE TEST2.OBJ CR.OBJ ;

When TEST.EXE is run, the first line prints garbled, while the second
prints correctly, as shown below:

   $#lkds
   b0

Note: If the C routine is changed so that near addressing is used, the
routine works correctly, as follows:

   #include <stdio.h>
   struct struct_string {
       int length;
       char *address;
                        };
   void crot(struct struct_string *string) /* changed to near pointer */
    {
         printf("%s\n", string->address);
    }

Making the above change correctly displays the following:

   a0
   b0

This change works because with near addressing, the C routine ignores
the VARSEG part of the address. This only works if the array a$ lies
within the default data segment.

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.