//HEAP_ZERO_MEMORY | HEAP_REALLOC_IN_PLACE_ONLY
調用HeapWalk函數時(shí),函數每次在PROCESS_HEAP_ENTRY結構中返回一個(gè)內存塊的信息,如果還有其他內存塊,函數返回TRUE,程序可以一直循環(huán)調用HeapWalk函數直到函數返回FALSE為止。在多線(xiàn)程程序中使用HeapWalk,必須首先使用HeapLock函數將堆鎖定,否則調用會(huì )失敗。
如果函數執行成功,返回值是非0值,否則返回0。一般來(lái)說(shuō),很少在程序中使用這兩個(gè)函數,而總是使用HEAP_NO_SERIALIZE標志來(lái)進(jìn)行同步控制,指定了這個(gè)標志的話(huà),HeapAlloc、HeapReAlloc、HeapSize和HeapFree等函數會(huì )在內部自己調用HeapLock和HeapUnlock函數。
5)HeapSize函數返回堆中某個(gè)內存塊的大小,這個(gè)大小就是使用HeapAlloc以及HeapReAlloc時(shí)指定的大?。?/div>
SIZE_T WINAPI HeapSize(
__in HANDLE hHeap, //堆句柄
__in DWORD dwFlags, //標志位
__in LPCVOID lpMem //需要返回大小的內存塊
);
6)HeapCompact函數用于合并堆中的空閑內存塊并釋放不在使用中的內存頁(yè)面:
SIZE_T WINAPI HeapCompact(
__in HANDLE hHeap,
__in DWORD dwFlags
);
下面實(shí)例代碼使用HeapWalk函數來(lái)遍歷一個(gè)堆:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int __cdecl _tmain()
{
DWORD LastError;
HANDLE hHeap;
PROCESS_HEAP_ENTRY Entry;
//
// Create a new heap with default parameters.
//
hHeap = HeapCreate(0, 0, 0);
if (hHeap == NULL) {
_tprintf(TEXT("Failed to create a new heap with LastError %d.\n"),
GetLastError());
return 1;
}
//
// Lock the heap to prevent other threads from accessing the heap
// during enumeration.
//
if (HeapLock(hHeap) == FALSE) {
_tprintf(TEXT("Failed to lock heap with LastError %d.\n"),
GetLastError());
return 1;
}
_tprintf(TEXT("Walking heap %#p...\n\n"), hHeap);
Entry.lpData = NULL;
while (HeapWalk(hHeap, &Entry) != FALSE) {
if ((Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
_tprintf(TEXT("Allocated block"));
if ((Entry.wFlags & PROCESS_HEAP_ENTRY_MOVEABLE) != 0) {
_tprintf(TEXT(", movable with HANDLE %#p"), Entry.Block.hMem);
}
if ((Entry.wFlags & PROCESS_HEAP_ENTRY_DDESHARE) != 0) {
_tprintf(TEXT(", DDESHARE"));
}
}
else if ((Entry.wFlags & PROCESS_HEAP_REGION) != 0) {
_tprintf(TEXT("Region\n %d bytes committed\n") \
TEXT(" %d bytes uncommitted\n First block address: %#p\n") \
TEXT(" Last block address: %#p\n"),
Entry.Region.dwCommittedSize,
Entry.Region.dwUnCommittedSize,
Entry.Region.lpFirstBlock,
Entry.Region.lpLastBlock);
}
else if ((Entry.wFlags & PROCESS_HEAP_UNCOMMITTED_RANGE) != 0) {
_tprintf(TEXT("Uncommitted range\n"));
}
else {
_tprintf(TEXT("Block\n"));
}
_tprintf(TEXT(" Data portion begins at: %#p\n Size: %d bytes\n") \
TEXT(" Overhead: %d bytes\n Region index: %d\n\n"),
Entry.lpData,
Entry.cbData,
Entry.cbOverhead,
Entry.iRegionIndex);
}
LastError = GetLastError();
if (LastError != ERROR_NO_MORE_ITEMS) {
_tprintf(TEXT("HeapWalk failed with LastError %d.\n"), LastError);
}
//
// Unlock the heap to allow other threads to access the heap after
// enumeration has completed.
//
if (HeapUnlock(hHeap) == FALSE) {
_tprintf(TEXT("Failed to unlock heap with LastError %d.\n"),
GetLastError());
}
//
// When a process terminates, allocated memory is reclaimed by the operating
// system so it is not really necessary to call HeapDestroy in this example.
// However, it may be advisable to call HeapDestroy in a longer running
// application.
//
if (HeapDestroy(hHeap) == FALSE) {
_tprintf(TEXT("Failed to destroy heap with LastError %d.\n"),
GetLastError());
}
return 0;
}
下面的實(shí)例代碼使用GetProcessHeaps函數獲得進(jìn)程中所有堆的句柄:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <intsafe.h>
int __cdecl _tmain()
{
DWORD NumberOfHeaps;
DWORD HeapsIndex;
DWORD HeapsLength;
HANDLE hDefaultProcessHeap;
HRESULT Result;
PHANDLE aHeaps;
SIZE_T BytesToAllocate;
//
// Retrieve the number of active heaps for the current process
// so we can calculate the buffer size needed for the heap handles.
//
NumberOfHeaps = GetProcessHeaps(0, NULL);
if (NumberOfHeaps == 0) {
_tprintf(TEXT("Failed to retrieve the number of heaps with LastError %d.\n"),
GetLastError());
return 1;
}
//
// Calculate the buffer size.
//
Result = SIZETMult(NumberOfHeaps, sizeof(*aHeaps), &BytesToAllocate);
if (Result != S_OK) {
_tprintf(TEXT("SIZETMult failed with HR %d.\n"), Result);
return 1;
}
//
// Get a handle to the default process heap.
//
hDefaultProcessHeap = GetProcessHeap();
if (hDefaultProcessHeap == NULL) {
_tprintf(TEXT("Failed to retrieve the default process heap with LastError %d.\n"),
GetLastError());
return 1;
}
//
// Allocate the buffer from the default process heap.
//
aHeaps = (PHANDLE)HeapAlloc(hDefaultProcessHeap, 0, BytesToAllocate);
if (aHeaps == NULL) {
_tprintf(TEXT("HeapAlloc failed to allocate %d bytes.\n"),
BytesToAllocate);
return 1;
}
//
// Save the original number of heaps because we are going to compare it
// to the return value of the next GetProcessHeaps call.
//
HeapsLength = NumberOfHeaps;
//
// Retrieve handles to the process heaps and print them to stdout.
// Note that heap functions should be called only on the default heap of the process
// or on private heaps that your component creates by calling HeapCreate.
//
NumberOfHeaps = GetProcessHeaps(HeapsLength, aHeaps);
if (NumberOfHeaps == 0) {
_tprintf(TEXT("Failed to retrieve heaps with LastError %d.\n"),
GetLastError());
return 1;
}
else if (NumberOfHeaps > HeapsLength) {
//
// Compare the latest number of heaps with the original number of heaps.
// If the latest number is larger than the original number, another
// component has created a new heap and the buffer is too small.
//
_tprintf(TEXT("Another component created a heap between calls. ") \
TEXT("Please try again.\n"));
return 1;
}
_tprintf(TEXT("Process has %d heaps.\n"), HeapsLength);
for (HeapsIndex = 0; HeapsIndex < HeapsLength; ++HeapsIndex) {
_tprintf(TEXT("Heap %d at address: %#p.\n"),
HeapsIndex,
aHeaps[HeapsIndex]);
}
//
// Release memory allocated from default process heap.
//
if (HeapFree(hDefaultProcessHeap, 0, aHeaps) == FALSE) {
_tprintf(TEXT("Failed to free allocation from default process heap.\n"));
}
return 0;
}
#include "stdafx.h"
#include <windows.h>
#include <iostream.h>
int main(int argc, char* argv[])
{
//創(chuàng )建堆
HANDLE hHeap = HeapCreate(
HEAP_GENERATE_EXCEPTIONS, //排除例外
10 << 10, //起始于10K
10 << 20); //終止于10K
if(hHeap != NULL)
{
//分配大的塊
LPVOID pLarge = HeapAlloc(
hHeap,
HEAP_ZERO_MEMORY,
1024);
//分配小的塊
LPVOID pSmall = HeapAlloc(
hHeap,
HEAP_ZERO_MEMORY,
1);
PROCESS_HEAP_ENTRY phe;
ZeroMemory(&phe, sizeof(phe));
HeapLock(hHeap);
while(HeapWalk(hHeap, &phe))
{
if(phe.lpData == pLarge)
{
cout<<"Found large block"<<endl;
}
else if(phe.lpData == pSmall)
{
cout<<"Found small block"<<endl;
}
else
{
cout<<"Anonymous block"<<endl;
}
}
HeapUnlock(hHeap);
HeapFree(hHeap, 0, pLarge);
pLarge = NULL;
HeapFree(hHeap, 0, pSmall);
pSmall = NULL;
}
return 0;
}