Page 1 of 1

Microsoft Windows Heap Memory Management A look at heaps and heaps of API calls

#1 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Posted 10 March 2010 - 02:06 AM

Microsoft Windows Heap Memory Management

This tutorial attempts to provide a simple and straight-forward understanding of the Windows Heap Memory Management system, the various API functions that exist and how to use them.

The Heap

The heap is a term given to a memory management system that provides a mechanism for allocating and deallocating memory in arbitary block sizes. If you have read my previous article on Virtual Memory Management, you will know that on the Windows operating system, pages are 4096 bytes in length. Allocating 4096 bytes for an object of say 20 bytes in length would waste 4076 bytes of a precious resource. Hence we have heap management which sits on top of Virtual Memory Management.

The heap management system is a chained list that keeps track of memory used and memory free. Let's take an example to illustrate that. Let's create an object called A that is 20 bytes in length on the heap. In addtion to the space for the object, the heap surrounds it in an object that contains a forward and backward pointer, and a guard at the end of some number of bytes. So what we end up with is this:

    signature
    flags
    object 'A'
    guard bytes
    forward chain pointer
    backward chain pointer



On a 32-bit system, this effectively means that there is an extra 40 bytes overhead associated with every object on the heap. Now let's create a second object of 1000 bytes called object 'B'. This means that we have

    signature
    flags
    object 'A'
    guard bytes
    forward chain pointer
    backward chain pointer
    signature
    flags
    object 'B'
    guard bytes
    forward chain pointer
    backward chain pointer



Now we add a third object called object 'C' and we have the following heap:

    signature
    flags
    object 'A'
    guard bytes
    forward chain pointer
    backward chain pointer
    signature
    flags
    object 'B'
    guard bytes
    forward chain pointer
    backward chain pointer
    signature
    flags
    object 'C'
    guard bytes
    forward chain pointer
    backward chain pointer



Let's now delete object 'A'. We end up with

    signature
    flags
    object 'A'
    guard bytes
    forward chain pointer
    backward chain pointer
    signature
    flags
    object 'B'
    guard bytes
    forward chain pointer
    backward chain pointer
    signature
    flags
    object 'C'
    guard bytes
    forward chain pointer
    backward chain pointer



Wait a second I hear you say, we have just deleted object 'A', so why is it still there? The answer is simple, the forward and backward chain pointers have been unchained from the allocated memory chain, and chained to the free memory chain. Some heap management systems such as windows will also blitz the 20 bytes of user memory to ensure you do not use it after it has been deallocated.

That hole where object 'A' was, is now only ever going to be used again if you request a heap allocation of 20 bytes or less. There is no space for any allocation larger than 20 bytes. Over time, this free space becomes a major issue. This is known as memory fragmentation and can have a significant impact on the amount of memory an application uses.

Microsoft heap management attempts to overcome this problem in several ways:

1. by ensuring that if you request a block of memory, that the size nearest your'
request is provided, so if we allocated an object 'D' which was 16 bytes in
length, it would probably give us the area that was occupied by object 'A'. In
other words, it would actually provide you with an object that was 4 bytes
longer than you requested.
2. Very large blocks are actually allocated using VirtualAlloc, rather than from
the heap itself.
3. Blocks deallocated next to each other are combined into a larger single block.

Heap Creation

To create a healp, we use the HeapCreate API call which takes three parameters, the global flags that will be used for the lifetime of the heap, the initial size of the heap, and whether or not the heap will be allowed to grow in size. The call returns a handle to the heap that has been created. More information about heap create may be found here on MSDN.

You may allocate more than one heap, simply by calling the HeapCreate function multiple times. This is particularly useful if your application is allocating relatively static objects once they have been created, but these calls are interspersed with allocations for objects that come and go. Here, you could create two heaps, one heap for the relatively static objects, and another heap for the dynamic objects. This is attempting to ensure objects with more or less the same period of life are kept together.

Another stratagy for multiple heap creation is based on object size. This is particularly good strategy for very dynamic objects that are allocated and deleted, whose size varies significantly. This minimises the amount of space wasted due to reallocation of objects that are actually larger than the object requires.

Heap Destruction

To destroy a heap, we use the HeapDestroy API call which takes the heap handle that was returned when the HeapCreate API call was made. More information about HeapDestroy may be found here on MSDN.

Allocating An Object On The Heap

To allocate an object on the heap we use the HeapAlloc API call which takes three parameters, the handle of the heap that is to be used for the allocation, the allocation flags and the size of the allocation. The return value is the address of the allocated object (that is the space that you can use). More information about heap create may be found here on MSDN.

Freeing An Object On The Heap

To free an object on the heap we use the HeapFree API call which takes three parameters, the handle of the heap that is to be used for the allocation, the allocation flags and the address of the allocation that was returned by the HeapAlloc API call. More information about heap create may be found here on MSDN.

Heap Integrity

It is important to understand that not all programs behave themselves :crazy:. I know that is hard to believe, but it is true. Whilst the heap memory management system attempts to spot rogue programs, there is a limit to it's capability. For eaxmple, if you ask for 10 bytes, but use 11 bytes, you have overwritten a guard byte which is not disasterous for the heap. Your program will continue to run without any problems whatsoever. If however you free that object, an exception will occur. Such problems are difficult to trace back to the point where the original corruption occurred, especially if the objects are being created all over the place (very bad programming practice, but I live in the real world and have seen such things!).

Another favourite error I have seen programmers make, is to allocate an object using the new operator, and then try and deallocate it using HeapFree. Each heap object has a unique signature which enables the heap memory management system ensure that only objects created against that heap handle are freed using the same heap handle.

There is an API call that can be used to check the integrity of the heap called HeapValidate. I am not going to discuss the call here, but details of the call may be found here here on MSDN.

This call can take a considerable length of time to run, if you have asked it to check a heap with thousands of objects!

Walking the Heap

You can walk through a heap using the HeapWalk API call. Again, I will not discuss this call here, but details of the call may be found here on MSDN.

Malloc And The new Operator

The new and delete operators uses malloc and free for their operation, and malloc and free do NOT use the heap memory management system (this is for historical reasons). Having stated that, the same rules, and problems exist when using these forms of memory allocation and deallocation.

Conclusion

There are often cases, even in C++, where using the Microsoft Windows Heap Management Functions are an absolote necessity. This necessity is bourne out of speed and memory usage. A good programmer needs to be aware of the alternatives, and use the right strategy for the right occasion (unless your code is going to be ported to another other operating system environment and maintained on both). Thinking that new and delete operators must only be used in C++ is so very wrong. It won't make you a bad programmer; it will simply mean that you are not an excellent programmer.

Is This A Good Question/Topic? 1
  • +

Page 1 of 1