Bagikan melalui


Melintas Daftar Timbunan

Contoh berikut memperoleh daftar timbunan untuk proses saat ini. Dibutuhkan rekam jepret dari timbunan menggunakan fungsi CreateToolhelp32Snapshot , lalu berjalan melalui daftar menggunakan fungsi Heap32ListFirst dan Heap32ListNext . Untuk setiap heap, ia menggunakan fungsi Heap32First dan Heap32Next untuk berjalan di blok heap.

Catatan

Heap32First dan Heap32Next tidak efisien, terutama untuk timbunan besar. Namun, mereka berguna untuk mengkueri proses lain di mana Anda biasanya harus menyuntikkan utas ke dalam proses lain untuk mengumpulkan informasi (API ini melakukan ini untuk Anda).

Lihat contoh kedua untuk alternatif yang setara, jauh lebih efisien, yang menggunakan HeapWalk alih-alih Heap32First dan Heap32Next. Perhatikan bahwa HeapWalk hanya dapat digunakan untuk proses yang sama.

#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;
}

Cuplikan kode berikut menggunakan fungsi HeapWalk untuk memandu tumpukan proses, menghasilkan output yang identik dengan contoh sebelumnya, tetapi jauh lebih efisien:

#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;
}

Berjalan timbunan dengan fungsi HeapWalk kira-kira linier dalam ukuran timbunan, sedangkan berjalan timbunan dengan fungsi Heap32Next kira-kira kuadrat dalam ukuran tumpukan. Bahkan untuk timbunan sederhana dengan 10.000 alokasi, HeapWalk berjalan 10.000 kali lebih cepat daripada Heap32Next sambil memberikan informasi yang lebih rinci. Perbedaan performa menjadi semakin dramatis seiring dengan bertambahnya ukuran tumpuk.

Untuk contoh yang lebih rinci tentang berjalan timbunan dengan fungsi HeapWalk , lihat Menghitung Heap.