7

我们一直在进行一次大的内存泄漏分析,发现其中一个促成因素是未删除事件上的委托,导致对象不能足够快(或有时永远)被 GC。

有人对如何在 FXCop 中编写规则以确保我们从处理程序中删除委托有任何想法吗?

我刚刚看到这个,因此我会在那里询问更多信息。

4

4 回答 4

3

你需要更具体。您无需检查所有事件委托是否都已取消订阅,因为在通常情况下,订阅者的寿命比发布者的寿命短。并且仅当您的订阅者看起来比发布者寿命更长时才会发生内存泄漏,因此存在引用,这会阻止 GC 收集发布者对象。

现在我们需要验证,如果您订阅了一个相对短暂的对象上的事件,您最终会取消订阅它。

在这种情况下,我可以提出一个启发式方法:分析所有局部变量对象(由当前代码块 {} 限定)和您显式 Dispose 的所有对象。对于这些对象上的每个事件,计算您订阅它们的次数和取消订阅的次数。如果第一个数字更大,则发出警告。

当然这并不能涵盖所有情况,但是我想没有静态方法可以涵盖此问题中的所有情况,您需要一些足够好的方法。

我不会在这里提到动态分析和代码审查的优势,因为它是一个单独的主题,与问题无关。

于 2009-06-12T14:43:38.333 回答
2

好的,除了实现实际检查的问题(在我看来,这与路径覆盖非常相似,因此不实用) - 这是编写新 FxCop 规则的方法:

起初,一些对我有帮助的文章:

实施一个简单的规则没什么大不了的。在您的项目中,您需要一个 Rules.xml 文件作为嵌入式资源(参见此处)。您从 Check() 方法派生您的类BaseIntrospectionRule并将您的代码添加到:

public override ProblemCollection Check( TypeNode typeNode )
{
  if( type.IsPublic )
  {
    Problems.Add( new Problem( ... ) );
  }
  return Problems;
}

我以前做过这个。我希望它仍然像描述的那样工作:)

于 2009-06-14T21:37:45.293 回答
1

您能否强制规定所有事件订阅都应通过 WeakReferences 处理?我认为这应该比分析程序的实际流程更容易实现。

于 2009-06-14T13:27:54.177 回答
0

假设实现处理程序的对象以某种方式具有对带有事件的对象的引用是否安全?如果是这种情况,你最好弄清楚如何以另一种方式打破循环。

不久前,我们在 ASP.NET 页面上的事件处理程序中也发生过类似的事情。实现处理程序的对象也有对页面的引用。在尽可能多地从架构上断开链接之后,剩下的几个链接被更改为 WeakReferences。没有更多的内存问题!

于 2009-05-12T20:36:08.047 回答