地址空间:系统中所有可用的内存地址。
物理内存:硬件中真实存在的存储空间。
虚拟地址空间:对于一个程序来说可以使用所有的内存空间中的地址,但实际往往不能做到和物理地址一 一对应,所以需要
转换操作,将程序中的虚拟地址转换为硬盘中的真实地址(分页和分段)。
API:
1.堆管理--获取、分配:
(1)HANDLE HeapCreate(DWORD flOptions,SIZE_T dwInitialSize,SIZE_T dwMaximumSize):
为当前进程申请一个新堆
flOptions:输入参数,创建堆的选项(允许用于代码执行、失败产生异常取代NULL、不连续存取)
dwInitialSize:输入参数,堆的初始化大小,自动进行对齐,为0自动指定为一个内存页的大小。
dwMaximumSize:输入参数,堆的最大值,为0时表示可增长的。
创建成功返回创建的堆的句柄。
(2)HANDLE GetProcessHeap(void):
获取当前进程的一个堆
成功返回堆的句柄,失败返回NULL。
(3)DWORD GetProcessHeaps(DWORD NumberOfHeaps,PHANDLE ProcessHeaps):
获取进程中的所有堆
NumberOfHeaps:输入参数,ProcessHeaps能够存储的个数。
ProcessHeaps:输出参数,指向用于保存结果的内存块(HANDLE类型的数组)。
返回值大于参数1,说明内存区域过小;小于参数1,成功;为0,失败。
(4)LPVOID HeapAlloc(HANDLE hHeap,DWORD dwFlags,SIZE_T dwBytes):
在指定堆上分配内存块
hHeap:输入参数,指定将要分配的堆。
dwFlags:输入参数,内存分配标志(如果错误抛出异常、不连续、内容清零)HEAP_GENERATE_EXCEPTION HEAP_NO_SERIALIZE HEAP_ZERO_MEMORY。
dwBytes:输入参数,需要分配的内存区域大小。
成功返回指向新分配的内存的指针,失败返回NULL。
(5)LPVOID HeapReAlloc(HANDLE hHeap,DWORD dwFlags,LPVOID lpMem,SIZE_T dwByte):
重新分配已经分配好的堆内存块的大小
lpMem:输入参数,原内存块地址。
(6)void GetSystemInfo(LPSYSTEM_INFO lpSystemInfo):
获取系统信息,包括OEN、内存分页大小、内存分配粒度、处理器信息、内存空间最大值最小值
lpSystemInfo:输出参数,指向SYSTEM_INFO结构的指针。
2.堆管理--获取大小、释放内存、销毁堆
(1)SIZE_T HeapSize(HANDLE hHeap,DWORD dwFlags,LPCVOID lpMem):
获取指定堆大小
hHeap:输入参数,要获取大小的内存块所在堆的句柄。
dwFlags:输入参数,内存块的标志(HEAP_NO_SERIALIZE)。
lpMem:输入参数,要获取大小的内存块指针。
成功返回内存块大小,失败返回-1.
(2)BOOL HeapFree(HANDLE hHeap,DWORD dwFlags,LPVOID lpMem):
释放HeapAlloc HeapReAlloc所分配的内存。
hHeap:输入参数,内存块所在的堆。
dwFlags:输入参数,内存块标志(HEAP_NO_SERIALIZE)
lpMem:输入参数,内存块的地址。
成功返回TRUE,否则返回FALSE。
(3)BOOL HeapDestroy(HANDLE hHeap):
销毁创建的堆
hHeap:输入参数,要销毁的堆的句柄。
成功返回TRUE,否则返回FALSE。
3.虚拟内存分配和释放
(1)LPVOID VirtualAlloc(LPVOID lpAddress,SIZE_T dwSize,DWORD flAllocationType,DWORD flProtect):
提交或者保留内存页面:空闲到保留/提交 保留到提交
lpAddress:输入参数,分配的起始位置。申请保留时向最近的一个分配粒度对齐,提交时向最近的一个页面对齐,NULL时自动决定
dwSize:输入参数,所需要分配的内存区域的大小
flAllocationType:输入参数,分配的类型。MEM_COMMIT:提交 MEM_RESERVE:保留 MEM_COMMIT|MEM_RESERVE:空闲到提交
flProtect:输入参数,内存保护属性
成功时返回分配到的内存的实际起始地址,失败时返回NULL
(2)BOOL VirtualFree(LPVOID lpAddress,SIZE_T dwSize,DWORD dwFreeType):
将内存状态从提交到保留 保留到空闲 或者同时进行,用于VirtualAlloc()的反向工作
lpAddress:输入参数,需要改变的内存区域的起始地址
dwSize:输入参数,需要改变的内存区域的大小,字节为单位
dwFreeType:输入参数,为MEM_DECOMMIT,将内存变为保留状态,dwSize=0时,lpAddress必须为内存区域的起始地址(VirtualAlloc的
返回值),整个区域成为Reserved状态;为MEM_RELEASE,释放内存,直接变为Free状态,dwSize=0时,lpAddress必须是内存区域的起始地址
(VirtuallAlloc的返回值)。两个值不能同时使用。
成功TRUE,失败FALSE。
(3)BOOL VirtualProtect(LPVOID lpAddress,SIZE_T dwSize,DWORD flNewProtect,DWORD lpflOldProtect):
lpAddress:输入参数,虚拟内存地址。
dwSize:输入参数,内存大小。
flNewProtect:输入参数,新的内存属性。
ipflOldProtect:输出参数,可以为NULL。
(4)BOOL VirtualLock(VirtualUnlock)(LPVOID lpAddress,SIZE_T dwSize):
lpAddress:输入参数,虚拟内存地址。
dwSize:输入参数,内存大小。
锁定内存、解锁内存。
(5)VirtualQuery(LPVOID lpAddress,MEMORY_BASIC_INFORMATION mbi,SIZE_T dwSize):
lpAddress:输入参数,虚拟内存地址。
mbi:输入参数,MEMORY_BASIC_INFORMATION结构体,存储内存信息。
dwSize:输入参数,内存大小。
mbi: State: 0x1000(提交状态) 0x2000(保留状态) Protect:保护属性,0x04表示可读写,0x00表示处于保留状态。
4.获得系统内存使用状态:
BOOL GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpBuffer):
lpBuffer:输出参数,指向MEMORYSTATUSEX结构体,保存系统信息
两种内存分配方式比较:
HeapAlloc基于堆分配内存管理,无需考虑页对齐、页面状态、页面属性等。堆内存管理依赖于虚拟内存管理,可以简单地
视为是对COMMIT状态的虚拟内存进行操作。
VirtualAlloc基于虚拟内存管理,原理是通过改变虚拟内存页面属性(空闲、保留、提交)来分配内存,更为底层。
所以堆管理函数更加灵活,分配简单,可以分配任意大小的内存,不受内存页对齐的影响。