2008 December 4th Thursday

本文介绍了Windows环境下如何使用GlobalAlloc等函数进行内存分配与管理,包括固定内存分配、可移动内存分配及共享内存的概念,并探讨了不同情况下选择不同内存类型的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 Memory Allocation

  When your program transfers something to the clipboard, it must allocate a memory
block and essentially hand it over to the clipboard. When we've needed to allocate
memory in earlier programs in this book, we've simply used the malloc function that
is supported by the standard C run-time library. However, because the memory blocks
stored by the clipboard must be shared among applications running under Windows, the
malloc function is inadequate for this task.

  Instead, we must dredge up memory allocation functions that were designed back in
the dark ages of Windows, in the days when the operating system ran in a 16-bit real-mode
memory architecture. These functions are still supported and you can still use them,
but they are not often needed.

  To allocate a memory block using the Windows API, you can call

hGlobal = GlobalAlloc (uiFlags, dwSize) ;

  The function takes two parameters: a possible series of flags and a size in bytes
of the allocated block. The function returns a handle of type HGLOBAL, called a "handle
to a global memory block" or a "global handle." A NULL return value indicates that sufficient
memory was not available for the allocation.

  Although the two parameters to GlobalAlloc are defined a bit differently, they are both
32-bit unsigned integers. If you set the first parameter to zero, you effectively use the
flag GMEM_FIXED. In this case, the global handle that GlobalAlloc returns is actually a pointer
to the allocated memory block.

  You can also use the flag GMEM_ZEROINIT if you'd like every byte in the memory block
to be initially set to zero. The succinct GPTR flag combines the GMEM_FIXED and GMEM_ZEROINIT
flags as defined in the Windows header files:

#define GPTR (GMEM_FIXED | GMEM_ZEROINIT)

There is also a reallocation function:

hGlobal = GlobalReAlloc (hGlobal, dwSize, uiFlags) ;

  You can use the GMEM_ZEROINIT flag to zero out the new bytes if the memory block is being enlarged.

  Here's the function to obtain the size of the memory block:

dwSize = GlobalSize (hGlobal) ;

and the function to free it:

GlobalFree (hGlobal) ;

  In the early 16-bit versions of Windows, the GMEM_FIXED flag was strongly discouraged because
Windows could not move the block in physical memory. In the 32-bit versions of Windows, the GMEM_FIXED
flag is normal because it returns a virtual address and the operating system can move the block in
physical memory by altering the page table. When programming for the 16-bit versions of Windows, using
the flag GMEM_MOVEABLE in GlobalAlloc was instead recommended. (Note that most dictionaries prefer the
spelling "movable" over "moveable," so that's how I'll spell the word otherwise.) There's also a shorthand
identifier identified in the Windows header files to additionally zero out the movable memory:

#define GHND (GMEM_MOVEABLE | GMEM_ZEROINIT)

  The GMEM_MOVEABLE flag allows Windows to move a memory block in virtual memory. This doesn't necessarily
mean that the memory block will be moved in physical memory, but the address that the application uses to
read and write to the block can change.

  Although GMEM_MOVEABLE was the rule in 16-bit versions of Windows, it is generally less useful now.
However, if your application frequently allocates, reallocates, and frees memory blocks of various sizes,
the virtual address space of your application can become fragmented. Conceivably, you could run out of virtual
memory addresses. If this is a potential problem, then you'll want to use movable memory, and here's how to do it.

  First define a pointer (for example, to an int type) and a variable of type GLOBALHANDLE:

int * p ;
GLOBALHANDLE hGlobal ;

  Then allocate the memory. For example:

hGlobal = GlobalAlloc (GHND, 1024) ;

  As with any Windows handle, don't worry too much about what the number really means. Just store it. When
you need to access that memory block, call

p = (int *) GlobalLock (hGlobal) ;

  This translates the handle into a pointer. During the time that the block is locked, Windows will fix
the address in virtual memory. It will not move. When you are finished accessing the block, call

GlobalUnlock (hGlobal) ;

  This gives Windows the freedom to move the block in virtual memory. To be really compulsively correct
about this process (and to experience the torments of early Windows programmers), you should lock and unlock
the memory block in the course of a single message.

  When you want to free the memory, call GlobalFree with the handle rather than the pointer. If you don't
currently have access to the handle, use the function

Global = GlobalHandle (p) ;

  You can lock a memory block multiple times before unlocking it. Windows maintains a lock count, and each
lock requires a corresponding unlock before the block is free to be moved. When Windows moves a block in
virtual memory, it doesn't need to copy the bytes from one location to another-it needs only manipulate the page
tables. In general, in the 32-bit versions of Windows the only real reason for allocating a movable block for
your own program's use is to prevent fragmentation of virtual memory. When using the clipboard, you should
also use movable memory.

  When allocating memory for the clipboard, you should use the GlobalAlloc function with both the GMEM_MOVEABLE
and the GMEM_SHARE flags. The GMEM_SHARE flag makes the block available to other Windows applicat
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值