Microsoft KB Archive/92942

{|
 * width="100%"|

GlobalReAlloc and GMEM_ZEROINIT Clarified

 * }

Q92942

-

The information in this article applies to:


 * Microsoft Windows Software Development Kit (SDK) versions 3.0, 3.1

-

SUMMARY
GlobalReAlloc is documented in the Windows API's reference manuals. This is a clarification of one of the flags you can set for GlobalReAlloc. Under one circumstance, when GlobalReAlloc is used with GMEM_ZEROINIT, it may not zero out all of the reallocated memory. This situation occurs when GlobalReAlloc is called to shrink a block of memory and then enlarge it.

MORE INFORMATION
When GlobalReAlloc is used with GMEM_ZEROINIT to increase the size of a block of memory in the global heap, it will zero out only the bytes it adds to the memory object; it does not initialize any of the memory that existed before the call.

Windows allocates memory from the global heap in multiples of 32 bytes; enhanced mode allocates memory on even 32-byte boundaries, and standard mode allocates memory on odd 32-byte boundaries (that is, /E allocates 32/64/96 bytes, /S allocates 16/48/80 bytes).Thus, when 10 bytes are requested, enhanced Windows actually allocates 32 bytes; when 55 bytes are requested, enhanced Windows allocates 64 bytes.

Suppose we have the following sequence of calls in Windows enhanced mode:

HGLOBAL hMem ;

// 32 bytes are actually allocated, not 10 because Windows // allocates global memory in multiples of 32 bytes. All // 32 bytes are initialized to zero. hMem = GlobalAlloc(GMEM_ZEROINIT | GMEM_FIXED, 10);

// Here, we allocate 32 more bytes and add them to the end of     // the first 32 bytes. ReAllocating to 40 bytes will cause the // block to be 64 bytes long. Only the second 32 // bytes are initialized to zero. The first 32 bytes are left // alone. hMem = GlobalReAlloc(hMem, 40, GMEM_ZEROINIT | GMEM_FIXED);

// Copy 39 bytes into the memory block. The first 39 bytes // will contain the string. lstrcpy((LPSTR)GlobalLock(hMem), &quot;This is a big enough string for our job&quot;)

// Now we shrink the block to 10 bytes. After the call, the // block will be 32 bytes long; the second 32 bytes are freed // and will no longer exist. The first 32 bytes will still // contain the same characters as before the call. hMem = GlobalReAlloc(hMem, 10, GMEM_ZEROINIT | GMEM_FIXED) ;

// Now, we enlarge the block back to 40 bytes. After the call, // the block will be 64 bytes long, and the second 32 bytes // will be initialized to zero. The first 32 bytes will be left // alone, however. The area between bytes 10 and 32 does *not* // get initialized! hMem = GlobalReAlloc(hMem, 40, GMEM_ZEROINIT | GMEM_FIXED) ; When GlobalReAlloc is called to shrink the block, we told it that we wanted only 10 bytes; that's all we should use. Then when we enlarge it back to 40 bytes, GlobalReAlloc only initializes the memory it adds to the current block--which is from bytes 33 to 64. The bytes between 10 and 40 were previously used, but GlobalReAlloc did not initialize them because it did not allocate them.

As a result, applications that call GlobalReAlloc to shrink and then re- enlarge a block of previously used data should not expect that all the bytes will be initialized to zero.

Additional query words: 3.00 3.10

Keywords : kb16bitonly

Issue type :

Technology : kbAudDeveloper kbWin3xSearch kbSDKSearch kbWinSDKSearch kbWinSDK300 kbWinSDK310