哪些 `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
也可用于编组 PVOID
或 SIZE_T
或 P<some_struct>
(尽管 out
或 ref
参数更自然)或任何其他应该是指针大小的类型。
任何超出单个函数(尤其是存储在字段中的函数)的 handle-as-IntPtr
都是 SafeHandle
包装器的一个很好的候选者,任何使用多个 IntPtr
s 同时进行(以防止意外混淆不兼容的句柄)。对于不涉及多线程并且不会让句柄超出其范围的简单一次性,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
烦恼。框架代码不一定被视为该做什么的好例子(大量代码违反了官方指南),但它确实是一回事。
我正在为从 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
也可用于编组 PVOID
或 SIZE_T
或 P<some_struct>
(尽管 out
或 ref
参数更自然)或任何其他应该是指针大小的类型。
任何超出单个函数(尤其是存储在字段中的函数)的 handle-as-IntPtr
都是 SafeHandle
包装器的一个很好的候选者,任何使用多个 IntPtr
s 同时进行(以防止意外混淆不兼容的句柄)。对于不涉及多线程并且不会让句柄超出其范围的简单一次性,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
烦恼。框架代码不一定被视为该做什么的好例子(大量代码违反了官方指南),但它确实是一回事。