System.Runtime.InteropServices。保险箱Handle 类

本文提供了此 API 参考文档的补充说明。

SafeHandle 类提供句柄资源的关键最终化,防止垃圾回收过早回收句柄,以及由操作系统回收以引用意外的非托管对象。

为什么保险箱Handle?

尽管重写 Object.Finalize 方法允许在垃圾回收对象时清理非托管资源,但在某些情况下,可以在平台调用中执行方法时通过垃圾回收回收最终对象。 如果终结器释放传递给该平台调用的句柄,则可能会导致处理损坏。 在平台调用期间(例如在读取文件时)阻止方法时,也可以回收句柄。

更关键的是,由于 Windows 主动回收句柄,因此可以回收句柄,并指向可能包含敏感数据的另一个资源。 这称为回收攻击,可能会损坏数据,并构成安全威胁。

保险箱Handle 的作用

SafeHandle 类简化了其中几个对象生存期问题,并与平台调用集成,以便不会泄露操作系统资源。 该 SafeHandle 类通过分配和释放句柄来解决对象生存期问题,而不会中断。 它包含一个关键终结器,可确保句柄已关闭,并保证在意外 AppDomain 卸载期间运行,即使在假定平台调用调用处于损坏状态的情况下也是如此。

由于 SafeHandle 继承自 CriticalFinalizerObject所有非关键终结器,因此在所有关键终结器之前调用所有非关键终结器。 对不再在同一垃圾回收传递期间生存的对象调用终结器。 例如, FileStream 对象可以运行正常的终结器来刷新现有缓冲数据,而不会造成处理泄露或回收的风险。 关键终结器和非关键终结器之间的这种非常薄弱的排序不适用于常规用途。 它主要是为了通过允许这些库在不改变其语义的情况下使用这些 SafeHandle 库来帮助迁移现有库。 此外,关键终结器及其调用的任何内容(如 SafeHandle.ReleaseHandle() 该方法)必须位于受限的执行区域中。 这会对可在终结器调用图中编写哪些代码施加约束。

平台调用操作会自动递增封装 SafeHandle 的句柄的引用计数,并在完成后递减这些句柄。 这可确保不会意外回收或关闭句柄。

通过向类构造函数中的SafeHandle参数提供值ownsHandle,可以在构造SafeHandle对象时指定基础句柄的所有权。 这会控制对象在释放对象后是否会 SafeHandle 释放句柄。 这对于具有特殊生存期要求的句柄或使用其生存期由其他人控制的句柄非常有用。

派生自 保险箱Handle 的类

SafeHandle 是操作系统句柄的抽象包装类。 从此类派生比较困难。 但可以使用 Microsoft.Win32.SafeHandles 命名空间中可提供以下项的安全句柄的派生类。