KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q50733: Huge Indirection May not Cross Segment Boundaries

Article: Q50733
Product(s): See article
Version(s): 5.10   | 5.10
Operating System(s): MS-DOS | OS/2
Keyword(s): ENDUSER | S_QuickC | mspl13_c
Last Modified: 30-NOV-1989

Microsoft C will never generate an array element that spans a segment
boundary. If a customer generates a scenario where this situation
occurs, Microsoft C will generate incorrect addresses for the element
that crosses the segment boundary. Placing elements such that they
could cross a segment boundary is an incorrect coding technique, not a
problem with Microsoft C and huge pointer addressing.

For instance, if a huge character buffer has been allocated and
structure data has been copied to this buffer, it is possible to
access this data in structure format by first setting a huge pointer
to the address of the structure you want and then specifying the huge
pointer followed by the structure pointer operator (->) and the name
of element you want to access.

However, if the structure you are looking at crosses a segment
boundary, then the indirection will fail. If the element of the
structure you are referencing is in another segment, your pointer will
usually end up offsetting by the correct number of bytes, but in the
current segment and not the next segment.

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

char huge buffer[70000];                /* Any huge buffer larger than 64K */
struct x { int x,y,z; };                /* Any structure */

/* Assume that buffer has been filled with many structures of type x.
   Since the structures were put into the buffer via byte copy, it
   is very likely that one of the structures will cross over the segment
   boundary. */

struct x huge *test_ptr;                /* A huge pointer to x */

test_ptr = (struct x huge *)(buffer+( 65536 - sizeof(struct x) ) );

/* test_ptr is now equal to some offset into huge character buffer.
   It is assumed that the user has given test_ptr a legitimate address
   of a structure that is contained in the buffer in an attempt to access
   that structure. */

test_ptr->z = 5;

/* The line above will create an incorrect address for the element z if
   z is in a segment other than the one specified by the huge pointer.
   This address will probably end up as the correct offset but in the
   same segment because, although the pointer is huge, it still will not
   compute the segment when used with indirection. This is also why
   huge structure arrays are padded and why huge arrays larger than
   128K must have elements whose size is a power of two. */

Note: This problem can avoided by simply creating a huge array of
structures instead of characters. The compiler will take care of
padding the array so that an array element (a structure) will not
cross a segment boundary.

This would seem to be a bug in the compiler since the huge pointer
cannot access data beyond a segment boundary. The situation where an
array element crosses a segment boundary would never be generated by
Microsoft C, however. Accordingly, the huge pointer arithmetic does
not account for such a situation. This is not a bug in the compiler,
but an error in the code.

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.