GlobalReAlloc() and GMEM_ZEROINIT Clarified

ID: 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), "This is a big enough string for our job")

      // 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
Version : WINDOWS:3.0,3.1
Platform : WINDOWS
Issue type :


Last Reviewed: November 4, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.