2

我得到一个 CA2006 (" Review usage of ... (a 'IntPtr' instance) to determine whether it should be replaced with a SafeHandle or CriticalHandle") 用于IntPtr返回ConvertStringSecurityDescriptorToSecurityDescriptor一个我知道的安全描述符,可以使用FreeLocal. 我只是简单地使用它,可能不会泄漏所涉及的内存。据我所知,没有关联内核句柄。

有很多SafeHandle子类,它们似乎都没有FreeLocal在包装对象的生命结束时调用。但是,我找不到任何关于哪些IntPtr实例(例如,由 Win32 API 返回)由 a 有效管理SafeHandle而哪些不是的确切信息。

我应该只取消 CA 警告吗?

更重要的是,如何确定IntPtr我将遇到的下一个用法相同?

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

4

1 回答 1

2

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

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

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

您的特定场景(将 SDDL 解析为安全描述符)已经在框架中以RawSecurityDescriptor.SecurityDescriptorSystem.Security.AccessControl. 对于它的价值,RawSecurityDescriptorP/InvokesConvertStringSecurityDescriptorToSecurityDescriptorW也不会打扰SafeHandle.​​ 框架代码不一定应该被视为做什么的一个很好的例子(大量代码违反了官方指南),但它是一些东西。

于 2017-06-14T12:58:01.703 回答