次の方法で共有


System.Runtime.InteropServices.SafeHandle クラス

この記事では、この API のリファレンス ドキュメントに補足的な解説を提供します。

SafeHandle クラスはハンドル リソースのクリティカルな最終処理を提供し、ハンドルがガベージ コレクションによって途中で再利用されるのを防ぎ、意図しないアンマネージ オブジェクトを参照するためにオペレーティング システムによってリサイクルされるのを防ぎます。

SafeHandle の理由

Object.Finalize メソッドをオーバーライドすると、オブジェクトがガベージ コレクションされるときにアンマネージ リソースをクリーンアップできますが、状況によっては、プラットフォーム呼び出し呼び出し内でメソッドを実行しているときに、ガベージ コレクションによってファイナライズ可能なオブジェクトを再利用できます。 ファイナライザーは、そのプラットフォーム呼び出しに渡されたハンドルを解放すると、破損を処理する可能性があります。 また、ファイルの読み取り中など、プラットフォーム呼び出しの呼び出し中にメソッドがブロックされている間にハンドルを再利用することもできます。

さらに重要なことに、Windows はハンドルを積極的にリサイクルするため、ハンドルをリサイクルし、機密データを含む可能性のある別のリソースを指す可能性があります。 これはリサイクル攻撃と呼ばれ、データが破損し、セキュリティ上の脅威になる可能性があります。

SafeHandle の機能

SafeHandle クラスは、これらのオブジェクトの有効期間に関するいくつかの問題を簡略化し、オペレーティング システム リソースがリークされないようにプラットフォーム呼び出しと統合されています。 SafeHandle クラスは、中断することなくハンドルを割り当てて解放することで、オブジェクトの有効期間の問題を解決します。 これには、プラットフォーム呼び出し呼び出しが破損した状態であると見なされた場合でも、ハンドルが閉じられ、予期しない AppDomain アンロード中に実行されることが保証される重要なファイナライザーが含まれています。

SafeHandleCriticalFinalizerObjectから継承されるため、クリティカルでないファイナライザーはすべて、クリティカルファイナライザーの前に呼び出されます。 ファイナライザーは、同じガベージ コレクション パス中に存在しなくなったオブジェクトに対して呼び出されます。 たとえば、 FileStream オブジェクトは、通常のファイナライザーを実行して、ハンドルがリークまたはリサイクルされるリスクなしに、バッファー内の既存のデータをフラッシュできます。 クリティカルファイナライザーと非クリティカル ファイナライザーの間のこの非常に弱い順序は、一般的な使用を目的としたものではありません。 主に、これらのライブラリがセマンティクスを変更せずに SafeHandle を使用できるようにすることで、既存のライブラリの移行を支援するために存在します。 さらに、クリティカル ファイナライザーと、 SafeHandle.ReleaseHandle() メソッドなどの呼び出しは、制約された実行領域に存在する必要があります。 これにより、ファイナライザーの呼び出しグラフ内で記述できるコードに制約が課されます。

プラットフォーム呼び出し操作は、 SafeHandle によってカプセル化されたハンドルの参照カウントを自動的にインクリメントし、完了時にそれらを減らします。 これにより、ハンドルが予期せずリサイクルされたり閉じたりすることがなくなります。

SafeHandle クラス コンストラクターのownsHandle引数に値を指定することで、SafeHandleオブジェクトを構築するときに、基になるハンドルの所有権を指定できます。 これにより、オブジェクトが破棄された後、 SafeHandle オブジェクトがハンドルを解放するかどうかを制御します。 これは、固有の有効期間要件を持つハンドルや、他のユーザーによって有効期間が制御されるハンドルを使用する場合に便利です。

SafeHandle から派生したクラス

SafeHandle は、オペレーティング システム ハンドルの抽象ラッパー クラスです。 このクラスからの派生は困難です。 代わりに、次の安全なハンドルを提供する Microsoft.Win32.SafeHandles 名前空間の派生クラスを使用します。