为什么这段代码导致内存泄漏?

Han*_*ber 8 debugging wcf static memory-leaks

我最近取得了WCF Windows服务的所有权,该服务大量使用以下静态Utility类来检索查找数据:

   public static class Utility
    {

       //begin code that causes increased memory consumption
        private static Dictionary<string, ErrorData> _errorData;

        internal static Dictionary<string, ErrorData> ErrorData

        {
            get
            {
                if (_errorData == null)
                {
                    _errorData = GetErrorData();
                }
                return _errorData;
            }

        }
        //end code that causes increased memory consumption

        /// GetErrorData method to get error messages from error xml
        /// </summary>         
        /// <returns>Dictionary of Error messages value for different fields.</returns>           
        internal static Dictionary<string, ErrorData> GetErrorData()
        {
            Dictionary<string, ErrorData> data = null;


                XmlDocument doc = LoadXmlDocument(Constants.ErrorMessagesFileName);
                XmlNodeList errorNode = doc.SelectNodes("/ErrorMessages/Error");
                data = new Dictionary<string, ErrorData>();

                foreach (XmlNode node in errorNode)
                {
                    ErrorData errorValues = new ErrorData();
                    errorValues.FieldName = node.Attributes["FieldName"].Value;
                    errorValues.ErrorMessage = node.Attributes["ErrorMessage"].Value;
                    data.Add(node.Attributes["code"].Value, errorValues);
                }


            return data;
        }
        internal static XmlDocument LoadXmlDocument(string xmlFileName)
        {
            XmlDocument doc = null;
            try
            {
                if (HttpRuntime.Cache[xmlFileName] == null)
                {
                    doc = new XmlDocument();
                    doc.Load(Constants.Folderpath + "\\" + xmlFileName);
                    HttpRuntime.Cache.Insert(xmlFileName, doc);
                }
                else
                {
                    doc = (XmlDocument)HttpRuntime.Cache[xmlFileName];
                }
            }
            catch (Exception ex)
            {
               //log
            }
            return doc;
        }
    }
Run Code Online (Sandbox Code Playgroud)

如您所见,静态ErrorData属性使用私有支持字段.ErrorData是一个使用文件系统上的XML资源构造的Dictionary,这就是为什么在初始检索时文件的内容存储在HttpRuntime.Cache中.

在正常负载下,该服务消耗大约120 MB的RAM.

在某些时候,团队成员认为有必要通过创建由延迟加载的静态字段支持的静态属性来引入另一级别的优化.无论如何,在仅几次调用服务之后,所述静态字段的存在导致相当严重的内存泄漏(500MB +).

我删除静态字段和属性(客户端调用Utility.GetErrorData())的那一刻,内存消耗回到正常水平.

任何人都可以解释为什么这个静态字段的存在导致内存泄漏?WCF服务正在使用InstanceContextMode.PerCall运行,如果这有所不同.

非常感谢.

Mar*_*ell 0

当您谈论更改时,我不完全确定您所说的代码更改是什么意思。然而,通过阅读代码,我猜测您最终会多次调用 GetErrorData,并且字典会填满大量重复条目。如果添加日志代码,会显示重复输入哪些代码?

马丁