This document provides a practical example of heap allocation in Windows programming, demonstrating how to dynamically allocate and deallocate memory using the heap functions.
Heap allocation is a fundamental memory management technique where memory is requested from the operating system at runtime. This is in contrast to stack allocation, where memory is automatically managed for local variables within function scopes. Heap allocation is essential for managing data structures whose size is not known at compile time or that need to persist beyond the scope of a function.
HeapAlloc: Allocates a block of memory from a specified heap.HeapFree: Releases a block of memory previously allocated by HeapAlloc.HeapCreate: Creates a new heap.HeapDestroy: Destroys a specified heap.The following C++ code demonstrates how to create a heap, allocate memory for an array of integers, use that memory, and then free it.
#include <windows.h>
#include <iostream>
int main() {
HANDLE hHeap = NULL;
int* pData = NULL;
const size_t NUM_ELEMENTS = 10;
const size_t ELEMENT_SIZE = sizeof( int );
const size_t ALLOCATION_SIZE = NUM_ELEMENTS * ELEMENT_SIZE;
// 1. Create a new heap
hHeap = HeapCreate( 0, ALLOCATION_SIZE, 0 );
if ( hHeap == NULL ) {
std::cerr << "Error creating heap: " << GetLastError() << std::endl;
return 1;
}
std::cout << "Heap created successfully." << std::endl;
// 2. Allocate memory from the heap
pData = (int*) HeapAlloc( hHeap, 0, ALLOCATION_SIZE );
if ( pData == NULL ) {
std::cerr << "Error allocating memory from heap: " << GetLastError() << std::endl;
HeapDestroy( hHeap ); // Clean up heap if allocation fails
return 1;
}
std::cout << "Memory allocated successfully." << std::endl;
// 3. Use the allocated memory
std::cout << "Initializing allocated memory..." << std::endl;
for ( size_t i = 0; i < NUM_ELEMENTS; ++i ) {
pData[i] = i * 10;
std::cout << "pData[" << i << "] = " << pData[i] << std::endl;
}
// 4. Free the allocated memory
if ( HeapFree( hHeap, 0, pData ) == 0 ) {
std::cerr << "Error freeing memory: " << GetLastError() << std::endl;
HeapDestroy( hHeap );
return 1;
}
std::cout << "Memory freed successfully." << std::endl;
pData = NULL; // Good practice to NULL the pointer after freeing
// 5. Destroy the heap
if ( HeapDestroy( hHeap ) == 0 ) {
std::cerr << "Error destroying heap: " << GetLastError() << std::endl;
return 1;
}
std::cout << "Heap destroyed successfully." << std::endl;
return 0;
}
HeapCreate: This function creates a new heap object. The parameters specify flags, initial size, and maximum size. In this example, we provide a reasonable initial size for our expected allocation.HeapAlloc: This function allocates a specified number of bytes from the heap. It returns a pointer to the allocated memory block or NULL if the allocation fails.HeapFree: This function deallocates a memory block previously allocated with HeapAlloc. It's crucial to free memory when it's no longer needed to prevent memory leaks.HeapDestroy: This function destroys the heap object, freeing all memory that is still allocated within it. It should be called when the heap is no longer required.When the above code is compiled and executed, the expected output would be similar to this:
NULL for allocation functions or 0 for free/destroy functions indicates an error, and GetLastError() can provide more details.HeapFree for allocated memory or HeapDestroy for a heap object when they are no longer needed will result in memory leaks, which can degrade application performance and stability.HeapCreate and HeapAlloc accept flags that can modify their behavior (e.g., for heap debugging or specific allocation strategies).HeapCreate allows you to manage private heaps, which can be useful for finer control or specific allocation patterns.