创建堆 HeapCreate

时间:2022-11-20 08:38:14

创建额外的堆的原因
1.对组件进行保护
2.更有效的内存管理
3.局部访问
4.避免线程同步开销
5.快速释放

HeapCreate函数原型:
HANDLE WINAPI HeapCreate(
_In_ DWORD  flOptions,
_In_ SIZE_T dwInitialSize,
_In_ SIZE_T dwMaximumSize

);

第一参数 flOptions 表示对堆的操作如何进行,可以是0,HEAP_NO_SERIALIZE,HEAP_GENERATE_EXCEPTIONS,HEAP_CREATE_ENABLE_EXECUTE。
默认情况下,对堆的访问会依次进行,多个线程会从同一个堆中分配释放内存,堆数据不被破坏。
但在多线程情况下,要尽量避免使用HEAP_NO_SERIALIZE。如果想在堆中放可执行代码,必须使用 HEAP_CREATE_ENABLE_EXECUTE。
第二参数dwInitialSize表示开始时分给堆的字节数。
第三参数dwMaximumSize表示所能增长到的最大大小,如果指定为0的话,则堆可以在需要的情况下不断增大。

从堆里分配内存块,只需调用HeapAlloc()函数
LPVOID
WINAPI
HeapAlloc(
_In_ HANDLE hHeap,
_In_ DWORD dwFlags,
_In_ SIZE_T dwBytes
);
这里说一下第三参数,用来指定一些标志,会对分配结果产生影响。目前只支持这三个参数,HEAP_ZERO_MEMORY,HEAP_GENERATE_EXCEPTIONS,HEAP_NO_SERIALIZE。

HEAP_ZERO_MEMORY是把内存清空,

HEAP_GENERATE_EXCEPTIONS告诉系统,如果没有足够的空间,就抛出异常,
HEAP_NO_SERIALIZE用来强制系统不要把这次分配结果与其他线程的访问排列起来,有可能破坏堆的完整性。

在分配大于1MB 的内存时,建议使用VirtualAlloc 函数。

低碎片堆
如果产生了内存碎片,我们可以强制操作系统使用低碎片堆的算法,《Windows核心编程》上举了一个例子,

VOID Sub_1()
{
HANDLE hCHeap = GetProcessHeap();
WCHAR buf[10] = { 0 };
ULONG ulHeapCompatibilityInformation;
ulHeapCompatibilityInformation = 2;
if (HeapSetInformation(hCHeap, HeapCompatibilityInformation, &ulHeapCompatibilityInformation,
sizeof(ulHeapCompatibilityInformation)))
{
wprintf(L"Heap algorithm set to %s Low-fragmentation heap(handle=0x%x)\n", buf[0], hCHeap);
}
else
{
wprintf(L"Unable to set Heap information to %s (handle=0x%x)GetLastError()= %d 0x%x\n",
buf[0], hCHeap, GetLastError(), GetLastError());
}
}