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

时间:2017-06-12 16:49:11

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

I am getting a CA2006 ("Review usage of ... (a 'IntPtr' instance) to determine whether it should be replaced with a SafeHandle or CriticalHandle") for an IntPtr returned from ConvertStringSecurityDescriptorToSecurityDescriptor which I know is a security descriptor that can be freed with a FreeLocal. I am using it only briefly and probably not leaking the memory involved. No kernel handle is associated as far as I can tell.

There are lots of SafeHandle subclasses and none of them appear to be calling FreeLocal at the end of life of the wrapped object. However, I can't find any definitive information concerning which IntPtr instances (say, returned by the Win32 API) are usefully managed by a SafeHandle and which ones are not.

Should I just suppress the CA warning?

More importantly, how to determine the same for the next IntPtr usage I will run into?

(A table that would map SafeHandle subclasses to the functions that will eventually free the handle would be great.)

1 个答案:

答案 0 :(得分:2)

如果你的问题是“是否已经有一个SafeHandle子类调用LocalFree来释放它的句柄”,那么是的,有 - SafeLocalAllocHandle。该类为internal,因此一般公众无法使用,但如果您想重新创建它,则代码很明显。如果你的问题是“我应该使用这样的课程吗”,那么这就是一个判断。 CA2006SafeHandle文档解释了设计原理:SafeHandle避免了多线程场景中句柄回收的问题,并且特别支持P / Invokes以确保在非托管代码之前不会意外释放句柄完成了。

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

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

您的特定场景(将SDDL解析为安全描述符)已经在RawSecurityDescriptor形式的框架中实现,您应该考虑使用它来重新发明轮子(和/或实现您自己的System.Security.AccessControl 1}}子类,如果Akka streams materialization concept中的现有类尚未涵盖它。为了它的价值,finally也P / Invokes到SecurityDescriptor并且不打扰{{1}框架代码不一定被视为做什么的好例子(大量代码违反了官方指南),但它是一些东西。