C# 代码审查:OutOfMemoryException问题

C# 代码审查:OutOfMemoryException问题,c#,.net,out-of-memory,C#,.net,Out Of Memory,我一直在下面的代码中抛出“System.OutOfMemoryException”。我不知道内存泄漏在哪里,如果有人能解释我做错了什么,那将是一个很大的帮助。谢谢 lock ((_tabs)) { System.IO.StreamReader sr = null; System.IO.MemoryStream ms = null; try { Type[] t = { typeof(tsgPublicDecs.tsgClsTab) };

我一直在下面的代码中抛出“System.OutOfMemoryException”。我不知道内存泄漏在哪里,如果有人能解释我做错了什么,那将是一个很大的帮助。谢谢

lock ((_tabs))
{
    System.IO.StreamReader sr = null;
    System.IO.MemoryStream ms = null;
    try
    {
        Type[] t = { typeof(tsgPublicDecs.tsgClsTab) };
        System.Xml.Serialization.XmlSerializer srl = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), t);
        ms = new System.IO.MemoryStream();
        srl.Serialize(ms, _tabs);
        ms.Seek(0, 0);
        sr = new System.IO.StreamReader(ms);
        return sr.ReadToEnd();
    }
    finally
    {
        if (((sr != null)))
        {
            sr.Close();
            sr.Dispose();
        }
        if (((ms != null)))
        {
            ms.Close();
            ms.Dispose();
        }
    }
}
编辑:回答以下几个问题:

  • _选项卡中没有填充任何内容(这就引出了许多其他问题,为什么要使用它,但我需要询问编写它的开发人员)
  • 引发错误的行是“srl.Serialize(ms,_tabs);”
  • 这个错误是随机的,我自己也无法复制它,但是让它运行几天就会抛出。因此,除了抛出的错误之外,我无法(不知道如何)获得任何信息
编辑2:
谢谢大家的意见。添加using并查找其他可能的内存泄漏似乎是最好的方法。很高兴看到人们能这么快伸出援手

根据选项卡的大小,您通过
sr.ReadToEnd()
读取整个序列化流的事实可能会导致此问题

需要一两个使用块

lock ((_tabs))
{
        Type[] t = { typeof(tsgPublicDecs.tsgClsTab) };
        System.Xml.Serialization.XmlSerializer srl = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), t);

        using ( System.IO.MemoryStream ms = new System.IO.MemoryStream())
        {  
           srl.Serialize(ms, _tabs);
           ms.Seek(0, 0);

           using (System.IO.StreamReader sr = new System.IO.StreamReader(ms))
           {
            return sr.ReadToEnd();
           }
        }


}
  • 正如其他人所说,我会怀疑

  • 将Visual Studio设置为在引发异常时中断并检查其大小

  • 如果要简单地处理,为什么不使用嵌套的“using”块而不是finally块呢

  • 当出现内存不足异常时,有多少线程正在运行?您的代码块可能在内存已被使用时挂起

  • 试试这个。。 这是我的。如果它不适合您,那么在您的tsgClsTab类中有一个循环引用。 还有,是的,查找“”;-)

    输出

    <?xml version="1.0"?>
    <ArrayOfAnyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <anyType xsi:type="tsgClsTab">
        <Id>1</Id>
      </anyType>
      <anyType xsi:type="tsgClsTab">
        <Id>2</Id>
      </anyType>
      <anyType xsi:type="tsgClsTab">
        <Id>3</Id>
      </anyType>
      <anyType xsi:type="tsgClsTab">
        <Id>4</Id>
      </anyType>
    </ArrayOfAnyType>
    
    
    1.
    2.
    3.
    4.
    
    您确定问题在这里吗

    你不是在别的地方泄露内存吗

    OutOfMemoryException可以从任何地方在内存分配时抛出,它发生在这里可能只是巧合

    尝试在内存分析器中分析应用程序,以查看您是否持有一些会导致内存“泄漏”的引用


    尝试从您的测试机中删除尽可能多的RAM(根据操作系统的不同,在XP上尝试降低到256/128 MB),并多次运行重复的用例(不一定只运行此代码的用例)。

    如果您可以改变它,这里还有另一个建议。用强类型泛型替换
    \u tabs
    '声明(我假设声明为
    ArrayList
    somwhere):

    旧:
    private ArrayList\u tabs=new ArrayList()
    新建:
    private List_tabs=new List()

    并以类似方式调整
    XmlSerializer
    实例化

    这就是说,经过一些非常基本的测试,我无法得到任何OOM异常发生。以下是其他人所说的使用简化:

        lock (_tabs)
        {
            Type[] t = { typeof(tsgPublicDecs.tsgClsTab) };
            System.Xml.Serialization.XmlSerializer srl = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), t);
            using (System.IO.Stream ms = new System.IO.MemoryStream())
            {
                srl.Serialize(ms, _tabs);
                ms.Seek(0, 0);
                using (System.IO.TextReader sr = new System.IO.StreamReader(ms))
                {
                    return sr.ReadToEnd();
                }
            }
        }
    

    编辑:你猜怎么着?我能够使OutOfMemoryException发生。但是只有这些项目中有10000个的arraylist,每个项目都有对前一个项目的引用。因此,当深入到它时,它是一个相当复杂的对象图,这可能就是您遇到的情况。

    如果要使用“try”,它应该是try{}catch(exception){}finally{}。也就是说,您错过了catchline抛出异常的原因是什么?在阻止IO之类的调用时保持锁几乎总是一个坏主意。顺便说一句,当抛出异常时,您可以发布堆栈跟踪吗?所有这些额外的括号都起作用了吗?如果(((ms!=nul)))是,将抛出哪一行异常?假设_tabs确实是tsgPublicDecs.tsgClsTab类型,那么它的大小/对象图对于序列化的性能和随后对该流的重新读取至关重要。话虽如此,我希望一堆括号不会占用内存。这段代码不会工作(或编译)。A) 您不需要带有“using”的finally块,并且B)您使用的MemoryStream超出了其作用域。这需要一个嵌套的using块。此外,即使此代码如kervin所述格式正确,它仍然无法解决您的内存不足问题,因为它只提供语法调整。(当然,这并不是说使用块不是一件美妙的事情。)好的,我错过了ms参数。固定的。这里没有finally块。虽然这段代码确实更干净,但就内存使用而言,它在语义上是相同的。这个问题清楚地表明他正在处理MemoryStream和StreamReader实例。为什么这是公认的答案?stewsha说异常可以追溯到Serialize()行;sr.ReadToEnd()引起这种情况的唯一方法是调用sr.ReadToEndAsync()
        lock (_tabs)
        {
            Type[] t = { typeof(tsgPublicDecs.tsgClsTab) };
            System.Xml.Serialization.XmlSerializer srl = new System.Xml.Serialization.XmlSerializer(typeof(ArrayList), t);
            using (System.IO.Stream ms = new System.IO.MemoryStream())
            {
                srl.Serialize(ms, _tabs);
                ms.Seek(0, 0);
                using (System.IO.TextReader sr = new System.IO.StreamReader(ms))
                {
                    return sr.ReadToEnd();
                }
            }
        }