産業用カメラ長期稼働クラッシュ調査(ハンドルリーク編)の知識マップ(知識グラフ)
type: Dataset

ハンドルリーク
type: Concept
definition: 参照カウントやハンドルカウントの数え違いなどにより、不要になったハンドル(ファイル・イベント・スレッド・GDIオブジェクト・アクセストークンなどカーネルオブジェクトへの参照)が解放されずに積み上がっていく状態。
alternative label: Handle Leak
verified by: Handle Count
may cause: 二次障害(secondary failure)

Handle Count
type: Concept
definition: プロセスが現在開いているハンドルの総数を表す、Windowsプロセスの計測値。
alternative label: ハンドルカウント
recommended for: 長時間運転後クラッシュの切り分け

failure path(異常系の途中失敗経路)
type: Concept
definition: timeout・reconnect・early returnなど、正常系ではなく処理が途中で失敗して抜けるコード経路。資源の解放漏れが起きやすい。
alternative label: Failure Path
alternative label: 異常系経路
may cause: ハンドルリーク
recommended for: 長時間運転後クラッシュの切り分け

メモリリーク
type: Concept
definition: 確保したメモリを解放し忘れ、Private BytesやCommitが増え続ける現象。
alternative label: Memory Leak
verified by: Private Bytes

Private Bytes
type: Concept
definition: プロセスが専有しているコミット済みメモリ量を表す、Windowsプロセスの計測値。
alternative label: プライベートバイト
recommended for: 長時間運転後クラッシュの切り分け

CreateEvent
type: Concept
definition: イベントオブジェクトを作成し、そのハンドルを返すWin32 API。呼び出し元は使用後にCloseHandleでハンドルを解放する必要がある。
alternative label: CreateEventW
requires: CloseHandle

CloseHandle
type: Concept
definition: プロセスのハンドルテーブルからエントリを1つ削除するWin32 API。「ファイルを閉じる」ことそのものではない。
alternative label: CloseHandle API
prevents: ハンドルリーク

構造化ログ(structured log)
type: Concept
definition: 文章ではなくkey=valueのように項目を決めて出力し、あとで機械的に集計できるログの形式。
alternative label: Structured Logging
recommended for: ハンドルリーク
recommended for: 二次障害(secondary failure)
recommended for: 長時間運転後クラッシュの切り分け
should precede: Application Verifier

Application Verifier
type: Concept
definition: Windowsのuser-modeアプリに対するランタイム検証ツールで、OS API利用や資源の扱い方を監視し誤用の検出や意図的な失敗の注入を行う。
alternative label: AppVerifier
alternative label: appverif.exe

RAII(Resource Acquisition Is Initialization)
type: Concept
definition: オブジェクトの生成時に資源を確保し、デストラクタでの解放を保証することで、途中失敗時にも資源が漏れないようにするC++の設計パターン。
alternative label: RAII
prevents: ハンドルリーク

二次障害(secondary failure)
type: Concept
definition: 資源の枯渇などが積み重なった結果として、本来の原因(漏らした場所)から離れた場所で表面化する障害。
alternative label: Secondary Failure

GDIオブジェクト
type: Concept
definition: ペン・ブラシ・デバイスコンテキストなどGDIが管理する描画資源で、プロセスあたりの既定上限に達するとそれ以上作成できなくなる。
alternative label: GDI Objects

長時間運転後クラッシュの切り分け
type: Concept
definition: 数日〜数週間の連続稼働後にだけ発生する障害を、資源の増え方と失敗経路の観測から原因究明する調査手法。
alternative label: Long-Run Crash Investigation

Thread Count
type: Concept
definition: プロセスが持つスレッド数を表す計測値。
alternative label: スレッド数
recommended for: 長時間運転後クラッシュの切り分け

subject: failure path(異常系の途中失敗経路)
predicate: mayCause
object: ハンドルリーク
description: timeout・reconnect・early returnなどの途中失敗経路でCloseHandleが呼ばれないと、ハンドルリークの原因になることがある。
evidence: 772.html
verified at: 2026-08-01
certainty: established

subject: ハンドルリーク
predicate: verifiedBy
object: Handle Count
description: ハンドルリークは、reconnectなどの操作後にHandle Countが戻らずじわじわ増え続けることで確認できる。
evidence: nf-processthreadsapi-getprocesshandlecount
verified at: 2026-08-01
certainty: established

subject: メモリリーク
predicate: verifiedBy
object: Private Bytes
description: メモリリークはPrivate Bytes(やCommit)がじわじわ増えることで確認できる。
evidence: psapi
verified at: 2026-08-01
certainty: established

subject: CreateEvent
predicate: requires
object: CloseHandle
description: CreateEventが返したイベントハンドルは、使用後にCloseHandleで解放することを前提とする。CloseHandle自体はファイル・プロセス・スレッド・ミューテックスなど多くのカーネルオブジェクトのハンドルを閉じるもので、CreateEventに限らない。
evidence: nf-synchapi-createeventw
verified at: 2026-08-01
certainty: established

subject: 構造化ログ(structured log)
predicate: recommendedFor
object: ハンドルリーク
description: create/openとclose/disposeの対応が崩れている箇所は、sessionId・resourceId・actionを持つ構造化ログで探すことが本記事の推奨対応である。
evidence: overview
verified at: 2026-08-01
certainty: established

subject: 構造化ログ(structured log)
predicate: shouldPrecede
object: Application Verifier
description: 後編で扱うApplication Verifierを使う前に、自前の構造化ログでlifetimeの崩れを追えるようにしておくのが土台になる。
evidence: application-verifier
verified at: 2026-08-01
certainty: established

subject: RAII(Resource Acquisition Is Initialization)
predicate: prevents
object: ハンドルリーク
description: RAII型でハンドルの生存期間をオブジェクトの生存期間に結び付けると、途中失敗の経路でも自動的にCloseHandleが呼ばれるためハンドルリークを防げる。
evidence: https://learn.microsoft.com/en-us/cpp/cpp/smart-pointers-modern-cpp
verified at: 2026-08-01
certainty: established

subject: RAII(Resource Acquisition Is Initialization)
predicate: uses
object: CloseHandle
description: Windowsのハンドルを保持するRAII型では、デストラクタが保持しているハンドルに対してCloseHandleを呼んで解放する。
evidence: nf-handleapi-closehandle
verified at: 2026-08-01
certainty: context-dependent

subject: Application Verifier
predicate: mitigates
object: ハンドルリーク
description: Application Verifierは低リソース時のfailure pathを前倒しで踏ませることで、ハンドルリークのような出にくい壊れ方を早期に表面化させる有効な手段とされる。
evidence: application-verifier
verified at: 2026-08-01
certainty: context-dependent

subject: ハンドルリーク
predicate: mayCause
object: 二次障害(secondary failure)
description: ハンドルリークは、蓄積の結果として新しいevent/file/threadを作るAPIの失敗という形で、数週間後に二次障害として表面化することが多い。クラッシュ地点は漏らした場所ではなく最後の被害者であることが多い。
evidence: 772.html
verified at: 2026-08-01
certainty: established

subject: 構造化ログ(structured log)
predicate: recommendedFor
object: 二次障害(secondary failure)
description: session/resource lifecycleの構造化ログをたどることで、落ちた場所ではなく漏らした場所という二次障害の本当の原因を特定することが本記事の推奨対応である。
evidence: overview
verified at: 2026-08-01
certainty: established

subject: CloseHandle
predicate: prevents
object: ハンドルリーク
description: 途中失敗の経路も含めてCloseHandleを漏れなく呼ぶことが、ハンドルリークの防止そのものになる。
evidence: nf-handleapi-closehandle
verified at: 2026-08-01
certainty: established

subject: GDIオブジェクト
predicate: mayCause
object: 二次障害(secondary failure)
description: GDIオブジェクトのハンドルを漏らした場合、プロセスあたりの既定上限(GDIProcessHandleQuotaで256〜65,536)がカーネルオブジェクトの理論上限より低いため、GUIが同居するアプリではこちらに先に達し、新しい描画資源を作れなくなって二次障害として表面化することがある。CreateEventのようなカーネルハンドルの漏れ自体はGDIの枠を消費しない。
evidence: gdi-objects
verified at: 2026-08-01
certainty: context-dependent

subject: Handle Count
predicate: recommendedFor
object: 長時間運転後クラッシュの切り分け
description: 長時間運転後にだけ落ちるアプリの切り分けでは、Private Bytesだけでなく Handle Countも必ず見ることが推奨される。
evidence: nf-processthreadsapi-getprocesshandlecount
verified at: 2026-08-01
certainty: established

subject: 構造化ログ(structured log)
predicate: recommendedFor
object: 長時間運転後クラッシュの切り分け
description: 落ちた瞬間の例外だけでなく、operation/session/resource lifecycleの構造化ログを先に整えておくことが、長時間運転後クラッシュの切り分けに効く。
evidence: overview
verified at: 2026-08-01
certainty: established

subject: failure path(異常系の途中失敗経路)
predicate: recommendedFor
object: 長時間運転後クラッシュの切り分け
description: 長時間運転後クラッシュの切り分けでは、月単位の再現を待たず、timeout・reconnect・early returnなどのfailure pathを短いループで大量に踏んで再現を圧縮することを本記事は推奨している。
evidence: 772.html
verified at: 2026-08-01
certainty: established

subject: Private Bytes
predicate: recommendedFor
object: 長時間運転後クラッシュの切り分け
description: 長時間運転後にだけ落ちるアプリの切り分けでは、Handle Countと合わせてPrivate Bytesも継続的に見ることで、主犯がメモリかハンドルかを切り分けられる。
evidence: psapi
verified at: 2026-08-01
certainty: established

subject: Thread Count
predicate: recommendedFor
object: 長時間運転後クラッシュの切り分け
description: 長時間運転の切り分けでは、スレッドリークの可能性を除外するため、Handle Count・Private Bytesと並んでThread Countも一緒に見ることが基本になる。
evidence: processes-and-threads
verified at: 2026-08-01
certainty: established