周遊堆積清單
下列範例會取得目前進程的堆積清單。 它會使用 CreateToolhelp32Snapshot 函式擷取堆積的快照集,然後使用 Heap32ListFirst 和 Heap32ListNext 函式逐步解說清單。 針對每個堆積,它會使用 Heap32First 和 Heap32Next 函式來逐步執行堆積區塊。
注意
Heap32First 和 Heap32Next 效率不佳,特別是針對大型堆積。 不過,它們很適合用來查詢您通常必須將執行緒插入其他進程,以收集這些 API 的資訊, (這些 API 為您) 。
如需使用 HeapWalk 而非 Heap32First 和 Heap32Next的對等、更有效率的替代方法,請參閱第二個範例。 請注意, HeapWalk 只能用於相同的程式。
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
int main( void )
{
HEAPLIST32 hl;
HANDLE hHeapSnap = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, GetCurrentProcessId());
hl.dwSize = sizeof(HEAPLIST32);
if ( hHeapSnap == INVALID_HANDLE_VALUE )
{
printf ("CreateToolhelp32Snapshot failed (%d)\n", GetLastError());
return 1;
}
if( Heap32ListFirst( hHeapSnap, &hl ) )
{
do
{
HEAPENTRY32 he;
ZeroMemory(&he, sizeof(HEAPENTRY32));
he.dwSize = sizeof(HEAPENTRY32);
if( Heap32First( &he, GetCurrentProcessId(), hl.th32HeapID ) )
{
printf( "\nHeap ID: %d\n", hl.th32HeapID );
do
{
printf( "Block size: %d\n", he.dwBlockSize );
he.dwSize = sizeof(HEAPENTRY32);
} while( Heap32Next(&he) );
}
hl.dwSize = sizeof(HEAPLIST32);
} while (Heap32ListNext( hHeapSnap, &hl ));
}
else printf ("Cannot list first heap (%d)\n", GetLastError());
CloseHandle(hHeapSnap);
return 0;
}
下列程式碼片段使用 HeapWalk 函式來逐步執行進程堆積,產生與上一個範例相同的輸出,但更有效率:
#include <windows.h>
#include <stdio.h>
int main( void )
{
DWORD heapIndex;
DWORD heapCount = 0;
PHANDLE heaps = NULL;
while (TRUE)
{
DWORD actualHeapCount = GetProcessHeaps(heapCount, heaps);
if (actualHeapCount <= heapCount)
{
break;
}
heapCount = actualHeapCount;
free(heaps);
heaps = (HANDLE*)malloc(heapCount * sizeof(HANDLE));
if (heaps == NULL)
{
printf("Unable to allocate memory for list of heaps\n");
return 1;
}
}
for (heapIndex = 0; heapIndex < heapCount; heapIndex++)
{
PROCESS_HEAP_ENTRY entry;
printf("Heap ID: %d\n", (DWORD)(ULONG_PTR)heaps[heapIndex]);
entry.lpData = NULL;
while (HeapWalk(heaps[heapIndex], &entry))
{
// Heap32First and Heap32Next ignore entries
// with the PROCESS_HEAP_REGION flag
if (!(entry.wFlags & PROCESS_HEAP_REGION))
{
printf("Block size: %d\n", entry.cbData + entry.cbOverhead);
}
}
}
free(heaps);
return 0;
}
使用 HeapWalk 函式進行堆積的逐步解說大致上是線性的堆積大小,而使用 Heap32Next 函式來逐步執行堆積大約是堆積的大小二次方。 即使是具有 10,000 個配置的一般堆積, HeapWalk 仍會比 Heap32Next 更快執行 10,000 倍,同時提供更詳細的資訊。 當堆積大小增加時,效能的差異會變得更明顯。