Memory Management
This section details the Windows API functions and structures used for managing memory resources within a Windows application. Efficient memory management is crucial for application performance, stability, and resource utilization.
Virtual Memory
Windows employs a virtual memory system that provides each process with its own private virtual address space. This abstraction allows applications to use more memory than is physically available and protects processes from interfering with each other's memory.
- Address Space: Each process has a 64-bit virtual address space (on 64-bit systems).
- Pages: The virtual address space is divided into fixed-size units called pages.
- Memory Mapping: Virtual addresses are mapped to physical memory (RAM) or page file contents by the Memory Manager.
Key Memory Management Concepts and Functions
1. Allocating and Freeing Memory
The primary functions for dynamic memory allocation are:
VirtualAlloc
: Reserves or commits a region of pages in the virtual address space of the calling process.VirtualAllocEx
: Reserves or commits a region of pages in the virtual address space of a specified process.VirtualFree
: Releases or decommits a region of pages within the virtual address space of the calling process.HeapAlloc
: Allocates a block of memory from a process's heap.HeapFree
: Frees a block of memory allocated from a process's heap.
For simple allocations, the C runtime functions like malloc
and free
are often used, which internally call the Windows heap functions.
2. Memory Protection
Memory pages can be protected to control access (read, write, execute). Functions for managing memory protection include:
VirtualProtect
: Changes the access protection for a region of pages in the virtual address space of the calling process.VirtualProtectEx
: Changes the access protection for a region of pages in the virtual address space of a specified process.
Common protection flags include:
PAGE_READONLY
PAGE_READWRITE
PAGE_EXECUTE_READ
PAGE_EXECUTE_READWRITE
3. Memory Mapping and Sharing
Windows provides mechanisms to map files into memory and to share memory between processes.
- File Mapping:
CreateFileMapping
: Creates or opens a named or unnamed file mapping object.MapViewOfFile
: Maps a view of a file mapping into the address space of the calling process.UnmapViewOfFile
: Unmaps a mapped view of a file from the process's address space.
- Shared Memory: File mapping objects can be used to create regions of memory that can be accessed by multiple processes.
4. Memory Status and Information
Functions to query memory usage and status:
GlobalMemoryStatusEx
: Retrieves current information about the amount of physical memory and commit charge for the computer.VirtualQuery
: Retrieves information about a region of pages.
Common Memory Management Tasks
Example: Allocating and Writing to Memory
#include <windows.h>
#include <stdio.h>
int main() {
LPVOID memoryBlock = NULL;
SIZE_T blockSize = 1024; // 1 KB
// Allocate 1 KB of memory with read/write access
memoryBlock = VirtualAlloc(
NULL, // Let the system determine the address
blockSize, // Size of the region to allocate
MEM_COMMIT | MEM_RESERVE, // Commit and reserve pages
PAGE_READWRITE // Memory protection flags
);
if (memoryBlock == NULL) {
wprintf(L"VirtualAlloc failed. Error: %lu\n", GetLastError());
return 1;
}
wprintf(L"Memory allocated at: %p\n", memoryBlock);
// Write data to the allocated memory
const char* message = "Hello, Windows Memory Management!";
strncpy((char*)memoryBlock, message, blockSize - 1);
((char*)memoryBlock)[blockSize - 1] = '\0'; // Ensure null termination
wprintf(L"Data written to memory: %s\n", (char*)memoryBlock);
// Free the allocated memory
if (VirtualFree(memoryBlock, 0, MEM_RELEASE) == 0) {
wprintf(L"VirtualFree failed. Error: %lu\n", GetLastError());
return 1;
}
wprintf(L"Memory freed.\n");
return 0;
}
Example: Shared Memory using File Mapping
This example demonstrates creating a shared memory section that can be written to by one process and read from by another (though both processes would need to run this code, with one acting as writer and the other as reader, or use synchronization primitives).
#include <windows.h>
#include <stdio.h>
#define SHARED_MEM_NAME L"MySharedMemory"
#define MEM_SIZE 256
int main() {
HANDLE hMapFile;
LPVOID lpMapAddress;
const char* msgToWrite = "This is shared data!";
// Create or open a named file mapping object
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // Use the paging file
NULL, // Default security attributes
PAGE_READWRITE, // Read/write access
0, // Maximum object size (high-order DWORD)
MEM_SIZE, // Maximum object size (low-order DWORD)
SHARED_MEM_NAME // Name of the mapping object
);
if (hMapFile == NULL) {
wprintf(L"CreateFileMapping failed. Error: %lu\n", GetLastError());
return 1;
}
// Map the file mapping into the address space
lpMapAddress = MapViewOfFile(
hMapFile, // Handle of the file mapping object
FILE_MAP_ALL_ACCESS, // Access mode
0, // Offset (high-order DWORD)
0, // Offset (low-order DWORD)
MEM_SIZE // Number of bytes to map
);
if (lpMapAddress == NULL) {
wprintf(L"MapViewOfFile failed. Error: %lu\n", GetLastError());
CloseHandle(hMapFile);
return 1;
}
wprintf(L"Shared memory mapped at: %p\n", lpMapAddress);
// Write data to the shared memory
strncpy((char*)lpMapAddress, msgToWrite, MEM_SIZE - 1);
((char*)lpMapAddress)[MEM_SIZE - 1] = '\0'; // Null terminate
wprintf(L"Data written to shared memory: \"%s\"\n", (char*)lpMapAddress);
// To read, another process would open the same mapping and use MapViewOfFile.
// For this example, we'll keep it mapped for demonstration.
// In a real application, you'd have synchronization logic.
wprintf(L"Press Enter to unmap and close...\n");
getchar();
// Unmap the view
if (!UnmapViewOfFile(lpMapAddress)) {
wprintf(L"UnmapViewOfFile failed. Error: %lu\n", GetLastError());
}
// Close the file mapping handle
CloseHandle(hMapFile);
return 0;
}
API Reference Table
Function | Description | Category |
---|---|---|
VirtualAlloc |
Reserves or commits a region of pages in the virtual address space. | Allocation |
VirtualFree |
Releases or decommits a region of pages. | Deallocation |
VirtualProtect |
Changes memory protection for a region of pages. | Protection |
CreateFileMapping |
Creates or opens a named or unnamed file mapping object. | File Mapping |
MapViewOfFile |
Maps a view of a file mapping into the address space. | File Mapping |
UnmapViewOfFile |
Unmaps a mapped view of a file. | File Mapping |
HeapAlloc |
Allocates memory from the process heap. | Heap Allocation |
HeapFree |
Frees memory from the process heap. | Heap Deallocation |
GlobalMemoryStatusEx |
Retrieves information about system memory. | Status |