哪些 `IntPtr` 风格是 `SafeHandle` 的候选者

Which `IntPtr` flavors are candidates for a `SafeHandle`

我正在为从 ConvertStringSecurityDescriptorToSecurityDescriptor 返回的 IntPtr 获取 CA2006(“Review usage of ... (a 'IntPtr' instance) to determine whether it should be replaced with a SafeHandle or CriticalHandle”),我知道这是一个可以用 [=13= 释放的安全描述符].我只是短暂地使用它,可能不会泄漏所涉及的内存。据我所知,没有关联内核句柄。

有很多 SafeHandle 个子类,其中 none 个似乎在包装对象生命周期结束时调用 FreeLocal。但是,我找不到任何关于哪些 IntPtr 实例(例如,由 Win32 API 返回)由 SafeHandle 有效管理而哪些不是。

我应该只抑制 CA 警告吗?

更重要的是,如何确定我将 运行 用于下一个 IntPtr 用法?

(将 SafeHandle 子类映射到最终释放句柄的函数的 table 会很棒。)

如果您的问题是 "is there already a SafeHandle subclass that calls LocalFree to free its handle",那么是的,有 -- SafeLocalAllocHandle. The class is internal, so it's not available to the general public, but the code is obvious if you wanted to recreate it. If your question is "should I use such a class", well, that's a bit of a judgment call. CA2006 and the SafeHandle 文档解释了设计原理:SafeHandle 避免了多线程场景中的句柄回收问题,并且具有特殊的支持 P/Invokes 以确保句柄在非托管代码完成之前不会被意外释放。

什么时候 IntPtr 可以被 SafeHandle 包裹的句柄?您无法从 IntPtr 中分辨出来,您必须知道返回 IntPtr 的函数是什么。它将记录您是否正在处理一个句柄,如果是,当您完成处理时应该如何关闭句柄(经常,但绝不总是,CloseHandle)。如果您只有 P/Invoke 签名,那么从技术上讲,您什么都没有。特别是,如果它是一个句柄,将无法确定应该调用什么函数来释放句柄。 IntPtr 也可用于编组 PVOIDSIZE_TP<some_struct>(尽管 outref 参数更自然)或任何其他应该是指针大小的类型。

任何超出单个函数(尤其是存储在字段中的函数)的 handle-as-IntPtr 都是 SafeHandle 包装器的一个很好的候选者,任何使用多个 IntPtrs 同时进行(以防止意外混淆不兼容的句柄)。对于不涉及多线程并且不会让句柄超出其范围的简单一次性,try .. finally 块可能就足够了。如果您愿意,为了保持一致性(或明确记录您正在处理的对象类型),所有内容都可以包含在 SafeHandle 中,但这并不一定会带来更好的结果。句柄回收是一个严重的问题,但在这里不是问题,因为句柄是针对本地内存的,并且可靠性不是问题,因为任何严重到足以绕过 finally 块的问题也严重到足以产生小内存泄漏不是问题。

您的特定场景(将 SDDL 解析为安全描述符)已经以 RawSecurityDescriptor, which you should consider using in favor of reinventing the wheel (and/or implementing your own SecurityDescriptor subclass if it's not already covered by the existing classes in System.Security.AccessControl 的形式在框架中实现。对于它的价值,RawSecurityDescriptor 也 P/Invokes 到 ConvertStringSecurityDescriptorToSecurityDescriptorW 并且不会为 SafeHandle 烦恼。框架代码不一定被视为该做什么的好例子(大量代码违反了官方指南),但它确实是一回事。