使用 SafeHandle 封装本机资源

更新:2007 年 11 月

TypeName

UseSafeHandleToEncapsulateNativeResources

CheckId

CA2006

类别

Microsoft.Reliability

是否重大更改

原因

托管代码使用 IntPtr 访问本机资源。

规则说明

在托管代码中使用 IntPtr 可能意味着潜在的安全性和可靠性方面的问题。必须检查所有使用 IntPtr 之处,以确定是否需要在该处使用 SafeHandle 或类似的技术。如果 IntPtr 表示某些被视为由托管代码所有的本机资源,如内存、文件句柄及套接字等,则会发生问题。即,托管代码应释放资源但却未能释放,结果造成资源泄漏。

在这样的情况下,如果允许对 IntPtr 进行多线程访问且 IntPtr 代表一种释放资源的方法,则还会存在安全性和可靠性方面的问题。这些问题包括在资源释放时回收 IntPtr 值,而与此同时另一个线程正在使用该资源,结果导致出现争用状态,其中一个线程可以读写与错误资源关联的数据。 例如,如果您的类型将某个操作系统句柄存储为一个 IntPtr,并且既允许用户调用 Close,又允许用户在不采用任何类型的同步的情况下调用同时使用该句柄的其他任何方法,则您的代码存在句柄回收问题。

这个句柄回收问题会导致数据损坏并且通常会造成安全漏洞。SafeHandle 及其同级类 CriticalHandle 提供了一种封装资源的本机句柄的机制,从而可以避免此类线程问题。另外,还可以使用 SafeHandle 及其同级类 CriticalHandle 来避免其他线程问题,例如,通过调用本机方法来仔细控制包含本机句柄副本的托管对象的生存期。在这种情况下,通常可以移除对 GC.KeepAlive 的调用。使用 SafeHandle 会导致潜在的性能开销(CriticalHandle 也有同样的问题,但程度要轻一些),通过仔细设计通常可以减少这些开销。

如何修复冲突

将所使用的 IntPtr 转换为 SafeHandle 以安全地管理对本机资源的访问。

何时禁止显示警告

不应禁止显示此警告。