I believe I have memory leak with some of my code that uses the XmlDocument class.
My program runs on a Windows 6.1.4 device (C#) and reads from a database on another server to see if any programs installed on the device need to be uninstalled and then reads from an XmlDocument to get the names of the programs that are uninstallable. The program then matches the lists and uninstalls accordingly, if necessary. This process is looped infinitely and runs in the background but what I'm noticing is that the memory creeps up slowly over time and the program eventually catches an OutOfMemoryException
.
If I comment out everything and do nothing in the loop, the memory stays right around 2MB consistantly. If I leave everything but the following code commented out then the memory usage goes up .05 megabytes every minute or so continuously. Those results are with having the loop sleep for 1 second. The regular sleep speed is about 10 minutes. Any thoughts as to what could be causing the leak and if it has anything to do with the XmlDocument class?
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
does eventually get used and is set to string.Empty
at the end of the loop. At first I had didn't have xmlDoc = null;
in my code but it didn't help either way. I've tried adding GC.Collect();
at the end of my loop and that seemed to help slow down the leak but it doesn't fix it entirely. Plus I've read it's not good practice to use it anyway.
Edit: So it seems to be the ConfigurationManager line that I commented out in my code above that has the memory leak. As soon as I comment out that line of code the memory leak stops. It starts back up when I uncomment this line. Is there something I need to do after making the call to ProcessConfiguration to release the memory?
Also, I am using the Microsoft.WindowsMobile.Configuration namespace for ConfigurationManager runtime version 1.1.4322 since System.Configuration does not exist in CF.
I had similar problem while iterating over many ~100 MB xml files. I tried all the things written above but none of them helped. Finally I separated xml processing into a separate dummy function and then garbage collection worked properly. I did something like this:
Function forGC did all the work. Now garbage collection understood when it was ok to remove an xml from memory
Looks like the answer to this is to do it natively using
DMProcessConfigXML()
. Using this method does not cause a memory leak. So there must be something within the wrapper that is not releasing its resources properly.You can change the type of cmdStr to a StringBuilder. Because string is immutable it gets copied around everytime you append something to the string.
In the code you show cmdStr gets bigger and bigger but I don't see anything ever happening with it... so this would cause your memory comsumption to grow indefinitely and result in OutOfMemory-Exception...