Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Poniższy przykład uzyskuje listę stertów dla bieżącego procesu. Tworzy zrzut sterty przy użyciu funkcji CreateToolhelp32Snapshot, a następnie przetwarza listę przy pomocy funkcji Heap32ListFirst i Heap32ListNext. Dla każdej sterty używa funkcji Heap32First i Heap32Next do przechodzenia przez bloki sterty.
Notatka
Heap32First i Heap32Next są nieefektywne, szczególnie dla dużych kup. Są one jednak przydatne w przypadku wykonywania zapytań dotyczących innych procesów, w których zazwyczaj trzeba wstrzyknąć wątek do innego procesu w celu zebrania informacji (te interfejsy API to robią za Ciebie).
Zobacz drugi przykład znacznie bardziej wydajnej alternatywy korzystającej z HeapWalk zamiast Heap32First i Heap32Next. Należy pamiętać, że HeapWalk można używać tylko w tym samym procesie.
#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;
}
Poniższy fragment kodu używa funkcji HeapWalk do przechodzenia przez sterty procesu, tworząc identyczny wynik jak w poprzednim przykładzie, ale znacznie wydajniej.
#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;
}
Przechodzenie przez stertę za pomocą funkcji HeapWalk jest w przybliżeniu liniowe względem rozmiaru sterty, podczas gdy przeglądanie sterty za pomocą funkcji Heap32Next jest w przybliżeniu kwadratowe względem rozmiaru sterty. Nawet dla skromnej sterty z 10 000 alokacji, HeapWalk działa 10 000 razy szybciej niż Heap32Next, podczas gdy podaje bardziej szczegółowe informacje. Różnica w wydajności staje się jeszcze bardziej dramatyczna w miarę wzrostu rozmiaru sterty.
Aby uzyskać bardziej szczegółowy przykład przeglądania sterty z funkcją HeapWalk, zobacz Wyliczanie sterty.