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

标签 c# winapi pinvoke roslyn-code-analysis safehandle

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

有很多SafeHandle子类,并且它们似乎都没有调用 FreeLocal在被包裹物体的生命周期结束时。但是,我找不到任何关于 IntPtr 的明确信息。实例(例如,由 Win32 API 返回)由 SafeHandle 有效管理。哪些不是。

我应该取消 CA 警告吗?

更重要的是,如何判断下一个IntPtr同样我会遇到什么用法?

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

最佳答案

如果您的问题是“是否已经有一个 SafeHandle 子类调用 LocalFree 来释放其句柄”,那么是的,有 - 它是 SafeLocalAllocHandle 。类(class)是internal ,所以它不适用于公众,但如果您想重新创建它,代码是显而易见的。如果您的问题是“我应该使用这样的类”,那么,这有点需要判断。 CA2006 SafeHandle 文档解释了设计原理:SafeHandle避免了多线程场景中句柄回收的问题,并且对 P/Invoke 具有特殊支持,以确保在非托管代码使用句柄之前不会意外释放句柄。

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

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

您的特定场景(将 SDDL 解析为安全描述符)已在框架中以 RawSecurityDescriptor 的形式实现。 ,您应该考虑使用它来重新发明轮子(和/或实现您自己的 SecurityDescriptor 子类,如果它尚未被 System.Security.AccessControl 中的现有类覆盖。对于它的值(value), RawSecurityDescriptor 也 P/Invokes ConvertStringSecurityDescriptorToSecurityDescriptorW 并且不关心 SafeHandle 。框架代码不一定应该被视为应该做什么的一个很好的示例(大量代码违反了官方指南),但它确实是这样。

关于c# - 哪些 `IntPtr` 风格是 `SafeHandle` 的候选者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44504715/

相关文章:

C++ 和 Windows - NtCreateThreadEx 函数的 DLL 注入(inject)不起作用

c# - 通过 C# 调用 Win32 api 失败!

c# - 为什么(错误地)使用 ref myarray[0] 传递数组可以工作,但仅在 32 位应用程序中有效?

c# - .NET UDP 客户端 : Error: An existing connection was forcibly closed by the remote host

c++ - PBM_SETMARQUEE是否不适用于垂直过程栏?

c# - 多态方法仅调用一次时运行两次

c - 请问 MessageBox() "eat"我的用户自定义消息?

c# - 将包含 int 和 int[] 的结构从 C# 编码到 C++

C# 内联检查语句不起作用

C# 甲骨文 : catch all exceptions relative to connectivity?