.NET RegEx“内存泄漏”调查

时间:2010-04-29 04:26:07

标签: .net regex memory-leaks

我最近在WinForms应用程序中查看了一些.NET“内存泄漏”(即意外的,挥之不去的GC根源对象)。在加载然后关闭一个巨大的报告之后,即使在几个gen2集合之后,内存使用量也没有像预期的那样下降。假设报告控件被一个迷路事件处理程序保持活着,我破解了打开WinDbg以查看发生了什么......

使用WinDbg,!dumpheap -stat命令报告了字符串实例消耗了大量内存。使用!dumpheap -type System.String命令进一步细化了这一点,我找到了罪魁祸首,一个用于报告的90MB字符串,地址为03be7930。最后一步是调用!gcroot 03be7930来查看哪些对象保持活着状态。

我的期望是不正确的 - 它不是一个悬挂在报告控件(和报告字符串)上的非挂钩事件处理程序,而是由System.Text.RegularExpressions.RegexInterpreter实例保留,该实例本身是{System.Text.RegularExpressions.CachedCodeEntry的后代。 1}}。现在,Regexs的缓存(有点)是常识,因为这有助于减少每次使用时重新编译Regex的开销。但这又与保持我的琴弦有关呢?

基于使用Reflector的分析,事实证明只要调用Regex方法,输入字符串就会存储在RegexInterpreter中。 RegexInterpreter保留此字符串引用,直到通过后续Regex方法调用将新字符串输入其中。我希望通过挂在Regex.Match实例上以及其他可能的类似行为。链是这样的:

  • Regex.Split,Regex.Match,Regex.Replace等
    • Regex.Run
      • RegexScanner.Scan(RegexScanner是基类,RegexInterpreter是上述子类)。

违规的Regex仅用于报告,很少使用,因此不太可能再次用于清除现有的报告字符串。即使后来使用正则表达式,也可能会处理另一份大型报告。这是一个相对重要的问题,只是简单的感觉很脏。

所有这一切,我找到了一些关于如何解决或至少解决这种情况的选项。我会先让社区回复,如果没有人提出来,我会在一两天内填补空缺。

2 个答案:

答案 0 :(得分:8)

您使用的是Regex实例还是采用字符串模式的静态Regex方法? According to this post,正则表达式实例不参与缓存。

答案 1 :(得分:0)

尝试切换到已编译的正则表达式 - 实例化需要更长时间,但可能不会受到这种奇怪的泄漏。

有关详情,请参阅http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regexoptions%28v=VS.100%29.aspx

或者,不要让Regex实例持续时间超过你需要的时间 - 为每个报告调用创建一个新的实例。