Microsoft KB Archive/51031

From BetaArchive Wiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

PRB: Global Variable Is Not Displayed Correctly by TextOut() ID Number: Q51031

2.03 2.10 3.00 WINDOWS


SYMPTOMS Define a global variable above the WinMain() routine with code similar to the following:

  #include <windows.h>
  LPSTR Str = "testing";

Then in the window procedure, use the TextOut() function to display “Str”. Garbage (strange characters) is displayed on the screen. This problem only occurs in real mode.

If “Str” is defined in the same manner, this time as a local variable, however, this problem does not occur.

CAUSE This problem is a result of the way the string was declared. By declaring “Str” as an LPSTR, it is statically declared as a far pointer. The far pointer is resolved when the application is first loaded. If DGROUP moves [which can happen when calling LocalAlloc() when yielding control to other applications with Yield() or GetMessage() or PeekMessage()], “Str” will become invalid. This happens to work for the local variable because the pointer is resolved when the function is entered, and the program is not yielding in the function. Therefore, the pointer remains valid throughout the life of the function call.

RESOLUTION Pointers should be declared and used as follows:

  1. Declare pointers to data in the data segment (DS) as NEAR. For example:

    char * Str = “testing”;

  2. Cast the pointer to FAR when making the following function call:

    TextOut(hDC, x, y, (LPSTR) Str, nCount);

    (Actually, if there is a prototype for the function, it is not necessary to cast the argument, since the prototype will perform an implicit cast.) The reason it works to dynamically cast a NEAR pointer to a FAR is that the compiler generates code to PUSH DS as the function call is being made. Even if the DS changes from time to time (as it often does in Windows), the code will always push the CURRENT value of DS on the stack when calling a function.

  3. Pointers should be declared as FAR only if they will be assigned values dynamically. For example:

    char * Str = “testing”; LPSTR lpStr; … lpStr = (LPSTR) Str; TextOut(hDC, x, y, lpStr, nCount);