我从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,因此公众不可用,但是如果您想重新创建它,则代码显而易见。如果您的问题是“我应该使用这样的类”,那么,这有点判断力。 CA2006SafeHandle文档解释了设计原理:SafeHandle避免了多线程方案中的句柄回收问题,并特别支持P / Invokes,以确保在处理非托管代码之前不会意外释放句柄。

IntPtr什么时候可以被SafeHandle包装?您将无法从IntPtr得知,您必须知道哪个函数正在返回IntPtr。它将记录您是否在处理手柄,如果是,则说明完成后如何关闭手柄(CloseHandle经常但并非总是如此)。如果您只有P / Invoke签名,那么从技术上讲,您将一无所有。特别是,如果是句柄,将无法确定应调用哪个函数来释放该句柄。 IntPtr也可以用于编组PVOIDSIZE_TP<some_struct>(即使outref参数对此更为自然)或任何其他应该具有指针大小的类型。

任何逃避单个函数(特别是存储在字段中的函数)的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/

10-08 21:50