我从Review usage of ... (a 'IntPtr' instance) to determine whether it should be replaced with a SafeHandle or CriticalHandle
返回的IntPtr
收到CA2006(“ ConvertStringSecurityDescriptorToSecurityDescriptor
”),我知道这是可以用FreeLocal
释放的安全描述符。我只是短暂地使用它,可能不会泄漏所涉及的内存。据我所知,没有内核句柄与之相关。
有许多SafeHandle
子类,在包装对象的生命周期结束时,似乎没有一个调用FreeLocal
。但是,我找不到有关哪些IntPtr
实例(例如,由Win32 API返回)由SafeHandle
有效管理而哪些没有的确切信息。
我应该否禁止CA警告?
更重要的是,如何确定我将要遇到的下一个IntPtr
用法?
(将SafeHandle
子类映射到最终将释放句柄的函数的表会很棒。)
最佳答案
如果您的问题是“是否已经有一个调用SafeHandle
释放其句柄的LocalFree
子类”,那么是的,它是SafeLocalAllocHandle
。该类是internal
,因此公众不可用,但是如果您想重新创建它,则代码显而易见。如果您的问题是“我应该使用这样的类”,那么,这有点判断力。 CA2006
和SafeHandle
文档解释了设计原理:SafeHandle
避免了多线程方案中的句柄回收问题,并特别支持P / Invokes,以确保在处理非托管代码之前不会意外释放句柄。IntPtr
什么时候可以被SafeHandle
包装?您将无法从IntPtr
得知,您必须知道哪个函数正在返回IntPtr
。它将记录您是否在处理手柄,如果是,则说明完成后如何关闭手柄(CloseHandle
经常但并非总是如此)。如果您只有P / Invoke签名,那么从技术上讲,您将一无所有。特别是,如果是句柄,将无法确定应调用哪个函数来释放该句柄。 IntPtr
也可以用于编组PVOID
或SIZE_T
或P<some_struct>
(即使out
或ref
参数对此更为自然)或任何其他应该具有指针大小的类型。
任何逃避单个函数(特别是存储在字段中的函数)的IntPtr
句柄都是SafeHandle
包装器的不错选择,就像同时使用多个IntPtr
一样(防止意外混淆不兼容的手柄)。对于不涉及多线程并且不让句柄逃脱其范围的简单一次性,一个try .. finally
块可能就足够了。如果需要,可以出于一致性考虑(或明确记录要处理的对象类型)将所有内容包装在SafeHandle
中,但这不一定会带来更好的结果。句柄回收是一个严重的问题,但这里不是要关注的问题,因为句柄是本地内存,可靠性也不是问题,因为任何严重到可以绕过finally
块的问题也都足够严重,以至于会导致少量内存泄漏。没问题。
您的特定场景(将SDDL解析为安全描述符)已经以RawSecurityDescriptor
的形式在框架中实现,您应该考虑使用它来重塑轮子(和/或实现自己的SecurityDescriptor
子类,如果不是的话)对于System.Security.AccessControl
中的现有类已经涵盖了。RawSecurityDescriptor
值得的是,ConvertStringSecurityDescriptorToSecurityDescriptorW
也P /调用SafeHandle
,并且不必理会。框架代码不一定应被视为怎么做(大量代码违反了官方准则),但这是必须的。
关于c# - 哪些IntPtr口味是SafeHandle的候选者,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44504715/