Applications often need to allocate blocks of memory to use while they are executing. There are various memory pools from which the required memory can be allocated.
A primary reason for allocating memory is to store data. When a Windows CE program begins, the system initially allocates 1 KB of memory to the stack. It then adds memory to the stack, as needed, one page at a time up to the fixed limit of 58 KB. To store data, you typically declare it on the stack.
Although the system can shrink a stack when memory is low, it does so only if all other sources of memory pages are exhausted. The stack is a good source of memory for data that changes frequently but is not appropriate for constant data. Neither is the stack the best source of large amounts of memory because the stack does not shrink until all pages are used.
Note Do not allow the stack for a thread to grow larger than 58 KB. Exceeding this threshold results in a system-access violation that causes the program to stop functioning.
Declaring static or global data causes the system to put the data in the read/write (R/W) data section of the application module. This section does not grow or shrink. Its size is set by the operating system when your application initializes. Determining the size of your application's data section allows you to estimate how much memory is available after your program is loaded. To do this, use the standard Win32 DumpBin utility, Dumpbin.exe, or the Remote Memory Viewer.
Use the information you obtain from the Memory Viewer to arrange your declared data to use as little memory as possible. Following are some suggestions for arranging your data:
The compiler will move declared constant data into the read-only data section.
Removing constant data from the R/W section and moving other data into the section uses space that would otherwise be wasted. This allows you to use less heap space.
It would be counterproductive to fill the section with additional data, and then have it grow by an entire page just to accommodate an additional variable.
Leave space for the loader.
When you declare static or global data objects, the operating system takes care of the memory storage, but you need to explicitly allocate memory. Although Windows CE has various functions for allocating memory, the most-used functions are VirtualAlloc, LocalAlloc, and HeapAlloc. To free the allocated memory, use the companion functions VirtualFree, LocalFree and HeapFree. To create and remove heaps, use HeapCreate and HeapDestroy. You can use a combination of these functions to minimize wasted RAM.
The VirtualAlloc function is the primary tool for allocating virtual memory in the Windows CE operating system. You use VirtualAlloc to directly allocate a number of memory pages. Although it is the most efficient tool for allocating a large memory object, you should not use VirtualAlloc to allocate small memory objects. Because VirtualAlloc can only allocate whole pages, if you need only a partial page, memory is wasted.
One advantage to using VirtualAlloc is that the allocated memory is easily returned if the system runs low on memory. When you are finished using the allocated memory, free it by using VirtualFree. The system returns the memory to the global virtual memory pool immediately.
Each process has its own default heap from which you can allocate memory. If a process needs memory, call LocalAlloc to allocate memory and LocalFree to free memory. Whenever you use the function LocalAlloc, if there is not enough available memory in the default heap to supply the requested amount of memory, the system adds to the amount of memory in the heap. When the system needs memory and tries to compact a heap, sometimes it cannot because there are partially-filled pages. Even when unused memory exists, if it is fragmented, the system cannot use it. This results in the number of available pages not corresponding to the total amount of free space in the heap. Though the operating system automatically shrinks the heap if it has one or more free memory pages, partially filled pages do not cause the system to shrink the heap.
The HeapCreate function creates a new heap for a process that is separate from the default heap for that process. Memory for the new heap is reserved, but it is not committed until needed. To allocate and free memory, use the HeapAlloc and HeapFree functions. You can free the new heap by using HeapDestroy, which returns the memory back to the virtual memory pool.
Creating a separate heap is a good allocation strategy when you need to make a lot of small, temporary memory allocations. For example, you could create a separate heap for an application that works with documents. This heap would allocate all memory for a document. When the user closed the document, the application would free the heap and return the memory to the global virtual memory pool. Using a separate heap keeps the size of the default heap small and avoids generating the numerous partially-filled pages you get when you use VirtualAlloc. Because each heap requires approximately 500 bytes of overhead, you should create separate heaps only if you expect to allocate at least 5 KB of memory.