次の方法で共有


ヒープ リストの走査

次の例では、現在のプロセスのヒープの一覧を取得します。 CreateToolhelp32Snapshot 関数を使用してヒープのスナップショットを受け取り、Heap32ListFirst 関数と Heap32ListNext 関数を使用して一覧を確認します。 ヒープごとに、 Heap32First 関数と Heap32Next 関数を使用してヒープ ブロックをウォークします。

注意

Heap32FirstHeap32Next は、特に大きなヒープでは非効率的です。 ただし、これらは、通常、情報を収集するためにスレッドを他のプロセスに挿入する必要がある他のプロセスに対してクエリを実行する場合に役立ちます (これらの API によって行われます)。

Heap32FirstHeap32Next の代わりに HeapWalk を使用する同等の、はるかに効率的な代替方法については、2 番目の例を参照してください。 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 関数を使用してヒープを歩くことは、ヒープのサイズでほぼ 2 次です。 割り当てが 10,000 個の控えめなヒープの場合でも、 HeapWalkHeap32Next の 10,000 倍高速に実行され、より詳細な情報が提供されます。 ヒープ サイズが大きくなると、パフォーマンスの違いはさらに劇的になります。

HeapWalk 関数を使用してヒープを歩く詳細な例については、「ヒープの列挙」を参照してください。