힙 목록 트래버스
다음 예제에서는 현재 프로세스에 대한 힙 목록을 가져옵니다. 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배 빠르게 실행되며 자세한 정보를 제공합니다. 힙 크기가 증가함에 따라 성능의 차이는 더욱 극적입니다.
HeapWalk 함수를 사용하여 힙을 걷는 자세한 예제는 힙 열거를 참조하세요.