【问题标题】:How to derive from the NameTable class to mitigate XmlReader memory leak?如何从 NameTable 类派生以减轻 XmlReader 内存泄漏?
【发布时间】:2011-06-14 09:41:57
【问题描述】:

This article 表示使用 XMLReader 会导致字符串内存泄漏。 (只需搜索“内存泄漏”即可找到该段落)。它说其中一项缓解措施是:

对此的一种缓解方法是推导出 来自 NameTable 类并强制执行 最大尺寸配额。 (不可能 防止使用 NameTable,或 切换 NameTable 时 满)

here 也提到了同样的问题和缓解措施。我的问题是,我如何“从 NameTable 类派生并执行最大大小配额”,正如文章所建议的那样?

【问题讨论】:

  • 内存泄漏,在 C# 中?
  • 更严肃地说:我想尽快摆脱 NameTable 并因此摆脱 XMLReader 是个好主意。这样,GC 将收集所有“虚拟泄露的数据”。

标签: c# wcf memory-leaks xmlreader


【解决方案1】:

我不知道这是否是唯一的方法,但在 WCF(您已经有这样的配额,MaxNameTableCharCount)中所做的是创建 System.Xml.XmlReader 的子类,或者通过自己实现阅读器功能(不好玩),或者委托给内部阅读器(更有可能)。您可以覆盖虚拟NameTable 属性以返回您自己的XmlNameTable 实现。此实现可以简单地将调用委托给原始名称表,但对其大小强制执行一些配额。

如果您需要解析的 XML 符合 WCF 阅读器支持的子集(即没有处理指令、没有实体引用、没有 DTD),您可以直接使用 WCF 阅读器(它们可以在服务之外使用) )。 XmlDictionaryReader.CreateTextReader 接受一个参数,该参数包含要对阅读器强制执行的配额,其中一个参数与名称表完全一致。

【讨论】:

  • 如果问题是由 WCF 使用 XmlReader/NameTable 引起的怎么办?我检查了 Memory Profiler,NameTable 实例似乎最终植根于 System.ServiceModel 类。
  • 这很奇怪,WCF 的 XmlNameTable 实现在 System.Runtime.Serialization 程序集中,并且仅在 XmlBaseReader 类中使用(根据 Reflector 的分析)。 System.ServiceModel 中的哪些类保留了名称表?
【解决方案2】:

这不是您问题的答案,但它可以帮助缓解您的“C# 内存泄漏问题”。

使用 C# 的 RAII 模式,您既可以处置非托管资源,也可以(当对象超出范围时)让 GC 处置托管资源。

我在工作中使用的代码是这样的:

void ParseXmlString(string p_xmlString)
{
   using (var stringReader = new StringReader(p_xmlString))
   using (var xmlReader = XmlReader.Create(stringReader))
   {
      while (xmlReader.Read())
      {
         // etc.
      }
   }
}

如您所见,xmlReader(和 stringReader)变量是本地变量,为每次解析尝试创建 (*)。

意味着它们将被收集 (**),从而避免了虚拟内存泄漏

查看 XmlReader 类,我发现无法覆盖 NameTable,因此无法提供替代实现。

对不起。

(*) 这不适合您的项目,但适合我的项目,所以...

(**) 我希望...你永远不会知道 GC,但是,你仍然可以尝试System.GC.Collect()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-27
    • 2014-05-10
    相关资源
    最近更新 更多