3

我相信我的一些使用 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 以释放内存后,我需要做些什么吗?

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

4

5 回答 5

2

我在迭代许多 ~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

于 2012-12-04T15:55:23.163 回答
0

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

于 2011-07-29T21:04:35.207 回答
0

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

于 2011-07-30T15:11:56.033 回答
0

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

于 2011-08-04T14:43:54.080 回答
0

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

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

于 2020-05-21T15:07:16.053 回答