다음 예제에서는 현재 프로세스에 대한 힙 목록을 가져옵니다. CreateToolhelp32Snapshot 함수를 사용하여 힙의 스냅샷을 만든 다음 Heap32ListFirst 및 Heap32ListNext 함수를 사용하여 목록을 순회합니다. 각 힙에 대해 Heap32First 및 Heap32Next 함수를 사용하여 힙 블록을 안내합니다.
메모
Heap32First 및 Heap32Next 특히 큰 힙의 경우 비효율적입니다. 그러나 일반적으로 정보를 수집하기 위해 스레드를 다른 프로세스에 삽입해야 하는 다른 프로세스를 쿼리하는 데 유용합니다(이러한 API는 자동으로 수행).
Heap32First 및 Heap32Next대신 HeapWalk 사용하는 더 효율적이고 동등한 대안은 두 번째 예제를 참조하세요. 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배 빠르게 실행되면서 더 자세한 정보를 제공합니다. 힙 크기가 증가함에 따라 성능의 차이는 더욱 극적입니다.