Microsoft KB Archive/51031: Difference between revisions

From BetaArchive Wiki
m (Text replacement - ">" to ">")
m (X010 moved page Microsoft KB Archive/Q51031 to Microsoft KB Archive/51031 without leaving a redirect: Text replacement - "Microsoft KB Archive/Q" to "Microsoft KB Archive/")
 
(No difference)

Latest revision as of 18:25, 12 August 2020

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

2.03 2.10 3.00 WINDOWS

Summary:

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);