Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Следующий пример показывает, как получить список куч для текущего процесса. Он принимает моментальный снимок куч с помощью функции createToolhelp32Snapshot, а затем проходит по списку с помощью функции Heap32ListFirst и Heap32ListNext. Для каждой кучи используются функции Heap32First и Heap32Next для обхода блоков кучи.
Заметка
Heap32First и Heap32Next неэффективны, в частности для больших куч. Однако они полезны для запроса других процессов, где обычно необходимо внедрить поток в другой процесс для сбора информации (эти 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 работает в 10 000 раз быстрее, чем Heap32Next, и при этом предоставляет более подробные сведения. Разница в производительности становится ещё более значительной по мере увеличения размера кучи.
Более подробный пример обхода кучи с функцией HeapWalk смотрите в разделе Перечисление кучи.