Window Handle の作成で例外発生!

"Error Creating Window Handle" 例外に遭遇した場合、特定のアプリでの現象なのか、システム全体での現象なのかによって話が変わってくる。
以下では、特定のアプリでの現象という想定で話を進める。

まずは、タスクマネージャーの「詳細」画面で、「ハンドル数」「ユーザーオブジェクト」「GDIオブジェクト」の列を追加し、該当プロセスの値を確認する。

2022-11-04-2333.png

Object Categories

システムには 3 つのカテゴリのオブジェクトが用意されている。
1. User Object:ウィンドウ管理をサポート
2. GDI (Graphics Device Interface) Object:グラフィックスをサポート
3. Kernel Object:メモリ管理、プロセス実行、およびプロセス間通信 (IPC) をサポート

プロセスのハンドルテーブルは Kernel Object のみに使用され、User Object や GDI Object には使用されない

User Object 数が上限に達していないか

  • User Object はほとんどが デスクトップヒープ から割り当てられる
  • 既定ではプロセス毎に 10,000 個の上限がある
  • この上限は以下のレジストリで変更できるが、上限に達した理由を調査する必要がある
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\USERProcessHandleQuota

2022-11-04-2305.png

GDI Object 数が上限に達していないか

  • GDI Object はデスクトップヒープからではなく セッションプール から割り当てられる
  • 既定ではプロセスごとに 10,000 個の上限がある
  • この上限は以下のレジストリで変更できるが、上限に達した理由を調査する必要がある
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\GDIProcessHandleQuota

2022-11-04-2318.png

ハンドルの上限に達した?

ハンドルテーブルエントリ

  • プロセスのハンドルテーブルエントリが枯渇する可能性は極めて低い
  • Windows が 32-bit, 64-bit 版どちらであっても、エントリ数は 約1,600万個 もあり基本的には無制限と考えられる
  • 特定の時点で 1万個を超えるハンドルを開いているプロセスは設計がよくないか、ハンドルリークが発生しているかのいずれか

ハンドルテーブルを格納するために必要なメモリ量

  • ハンドルテーブルを格納するのに必要なメモリは ページプール から割り当てられる
  • 最大数のハンドル(約1,600万個)を格納するのに必要なメモリ量は、64-bit Windows の場合 256MB

2022-11-05-0925.png

2022-11-05-0926.png

オブジェクトの種類ごとのハンドル数

Sysinternals の handle ユーティリティを使うと、開かれているオブジェクトの種類ごとのハンドル数とその合計値を確認できる。

handle -s [-p <process name | pid>]

2022-11-27-2338.png

参考