下列範例會取得目前進程的堆積清單。 它會使用 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 倍,並提供了更詳細的資訊。 當堆積大小增加時,效能的差異會變得更加戲劇性。