【问题标题】:Memory Leak with XmlDocument()内存泄漏与 XmlDocument()
【发布时间】:2011-10-16 06:39:35
【问题描述】:

我相信我的一些使用 XmlDocument 类的代码存在内存泄漏。

我的程序在 Windows 6.1.4 设备 (C#) 上运行,并从另一台服务器上的数据库中读取,以查看是否需要卸载设备上安装的任何程序,然后从 XmlDocument 中读取以获取程序的名称可卸载的。然后程序匹配列表并在必要时进行相应的卸载。这个过程无限循环并在后台运行,但我注意到内存随着时间的推移缓慢上升,程序最终捕获OutOfMemoryException

如果我注释掉所有内容并且在循环中什么都不做,内存始终保持在 2MB 左右。如果我留下所有内容,但将以下代码注释掉,那么内存使用量每分钟连续增加 0.05 兆字节左右。这些结果是让循环睡眠 1 秒。正常的睡眠速度约为 10 分钟。关于可能导致泄漏的原因以及它是否与 XmlDocument 类有关的任何想法?

foreach (string programName in uninstallPrograms)
{
    XmlDocument xmlDoc1 = new XmlDocument();
    xmlDoc1.LoadXml("<wap-provisioningdoc>" +
          "  <characteristic type=\"UnInstall\">" +
          "    <characteristic type=\"" + programName + "\">" +
          "     <parm name=\"uninstall\" value=\"1\"/>" +
          "    </characteristic>" +
          "  </characteristic>" +
          "</wap-provisioningdoc>");

    xmlDoc1 = ConfigurationManager.ProcessConfiguration(xmlDoc1, true);

    cmdStr += "DELETE FROM DEVICE_APPS WHERE ID = " + deviceAppIDList[count++] + "; ";

    xmlDoc1 = null;
}

// Check for pre-installed apps to uninstall
count = 0;

XmlDocument xmlDoc2 = new XmlDocument();

xmlDoc2.LoadXml("<wap-provisioningdoc><characteristic-query type=\"UnInstall\"/>" +
        "</wap-provisioningdoc>");

/**** The line below seems to be the cause of the memory leak ****/
//xmlDoc2 = ConfigurationManager.ProcessConfiguration(xmlDoc2, true);

XmlNodeList xmlNodeList = xmlDoc2.SelectNodes("wap-provisioningdoc/" +
        "characteristic[@type='UnInstall']/characteristic/@type");

xmlDoc2 = null;

cmdStr 最终会被使用,并在循环结束时设置为string.Empty。起初我的代码中没有xmlDoc = null;,但这两种方式都没有帮助。我尝试在循环末尾添加GC.Collect();,这似乎有助于减缓泄漏,但并不能完全解决它。另外,我读过无论如何使用它都不是一个好习惯。

编辑:所以似乎是我在上面的代码中注释掉的 ConfigurationManager 行存在内存泄漏。一旦我注释掉那行代码,内存泄漏就会停止。当我取消注释此行时,它会重新启动。调用 ProcessConfiguration 释放内存后我需要做些什么吗?

另外,我正在为 ConfigurationManager 运行时版本 1.1.4322 使用 Microsoft.WindowsMo​​bile.Configuration 命名空间,因为 CF 中不存在 System.Configuration。

【问题讨论】:

  • 顺便说一句,当有人添加一个重要的程序名时,你的代码就是吐司;将字符串连接到 xml 而不对其进行编码是危险的 - 损坏的 xml 是肯定的。
  • 仅供参考。请注意我如何编辑您问题的代码部分。您只需在代码行前加上四个空格。不需要 precode HTML 标签。
  • 这是真的 Marc,但填充 programName 的数据是从数据库中检索的,而数据库是从手持设备本身填充的。所以是的,如果数据库被损坏,肯定会有一个问题,但一个更大的问题。感谢犬夜叉的修复!

标签: c# memory-leaks windows-mobile xmldocument windows-mobile-6.1


【解决方案1】:

在您显示的代码中 cmdStr 变得越来越大,但我看不到它发生任何事情...所以这会导致您的内存消耗无限增长并导致 OutOfMemory-Exception...

【讨论】:

  • 对不起,我应该提到该变量稍后会使用并在循环结束时使用 cmdStr = string.Empty; 重置。我没有将所有代码都放在循环中,只是因为那里有很多代码。不过,我已将其范围缩小到这一块。
  • Global.WriteToFile 是做什么的?您能否评论这些调用并再次检查或显示此方法的源代码?
  • 我删除了这些行,它们只是为了写到我保留的日志文件中。
  • 是的 - 但有什么改变吗?内存增长还是一样还是变慢了?
  • 内存增长还是一样。
【解决方案2】:

您可以将 cmdStr 的类型更改为 StringBuilder。 因为字符串是不可变的,所以每次你在字符串上附加一些东西时它都会被复制。

【讨论】:

    【解决方案3】:

    看起来这个问题的答案是使用 DMProcessConfigXML() 在本地完成它。使用此方法不会导致内存泄漏。因此,包装器中一定有一些东西没有正确释放其资源。

    【讨论】:

      【解决方案4】:

      我在迭代许多 ~100 MB xml 文件时遇到了类似的问题。我尝试了上面写的所有东西,但没有一个有帮助。最后,我将 xml 处理分离为一个单独的虚拟函数,然后垃圾收集正常工作。我做了这样的事情:

      function f()
      {
          FileInfo[] rgFiles = di.GetFiles("*.xml.gz", SearchOption.TopDirectoryOnly);
          //process all *.xml.gz files in folder
          foreach (FileInfo fi in rgFiles)
          {
              forGC(fi);
          }
      }
      

      函数 forGC 完成了所有工作。现在垃圾收集了解何时可以从内存中删除 xml

      【讨论】:

        【解决方案5】:

        重复的问题 https://stackoverflow.com/questions/42226993/how-to-dispose-xmldocument 寻找 György Kőszeg 的答案。

        using 语句会调用 Dispose 来清理资源。 XmlDocument 不是 IDisposable,但 FileStream 是。

        【讨论】:

          猜你喜欢
          • 2019-08-08
          • 2012-08-21
          • 2016-01-25
          • 1970-01-01
          • 2015-04-15
          • 2014-03-26
          • 2012-07-09
          • 2011-01-04
          • 2015-06-28
          相关资源
          最近更新 更多