使用字符串避免内存泄漏

时间:2015-04-07 14:10:06

标签: c# string memory-leaks

我在解析器中发现内存泄漏。我不知道如何解决这个问题。 让我们看看基本路由。

    private void parsePage() {
        String[] tmp = null;

        foreach (String row in rows) {
            tmp = row.Split(new []{" "}, StringSplitOptions.None);

            PrivateRow t = new PrivateRow();

            t.Field1 = tmp[1];
            t.Field2 = tmp[2];
            t.Field3 = tmp[3];
            t.Field4 = String.Join(" ", tmp);

            myBigCollection.Add(t);
        }
    }


    private void parseFromFile() {
        String[] tmp = null;

        foreach (String row in rows) {
            PrivateRow t = new PrivateRow();

            t.Field1 = "mystring1";
            t.Field2 = "mystring2222";
            t.Field3 = "mystring3333";
            t.Field4 = "mystring1 xxx yy zzz";

            myBigCollection.Add(t);
        }
    }

在集合上启动 parsePage()(行是100000个元素的列表)使我的应用程序从20MB增长到70MB。

启动 parseFromFile(),从文件读取SAME集合,但避免拆分/加入,大约需要1MB。

使用MemoryProfiler,我看到" t" fields和PrivateRow ,kkep引用String.Split()数组和Split.Join。 我想这是因为我分配了一个可以被垃圾收集的引用而不是副本。

好吧,使用70mb并不是什么大不了的事,但是当我开始制作时,有很多网站,它可以提高2.5-3GB ......

干杯

4 个答案:

答案 0 :(得分:3)

这本身并不是内存泄漏。它实际上表现得很好。你的第二个函数使用如此少的内存的原因,仅仅是因为你只使用了四个字符串。这四个字符串中的每一个只分配一次,后续使用新t.Fieldx实例的字符串实际上引用相同的字符串值。字符串是不可变的,因此如果您多次引用相同的字符串值,它可以由相同的字符串实例处理。有关详细信息,请参阅this article on String in .NET上标有“实习”的段落。

在你的第一个函数中,每个字段都有大部分不同的字符串,每次循环都有。这只是更加多样化的数据。只要您的PrivateRow对象存在,这些字符串保留的事实就是您希望发生的事情。

答案 1 :(得分:2)

你根本没有内存泄漏,只是垃圾收集器需要时间来处理它。

  

我想这是因为我可以分配一个引用,而不是一个副本   被垃圾收集。

这是不正确的假设。在分配期间复制string,即使它是引用类型。它是BCL内部的特殊,种类,独特的类型。

如果您有严重的内存压力,那么可能的解决方案呢?如果您要从文件中处理大量字符串,则可以查看2个选项。

1)通过读取srteam(不是一次加载)按顺序处理它们。在内存中尽可能少地加载/需要/生成。

2)再次使用MemoryMappedFile加载数据块并按顺序处理它们。

第二名可以与第一名合并。

答案 2 :(得分:0)

像其他人所说的那样,这里没有内存泄漏的证据,只是延迟了垃圾收集。最终应该清理所有内存。

话虽如此,您可以采取一些措施来帮助降低内存使用率或更快地恢复内存:

1)您应该能够替换

t.Field4 = String.Join(" ", tmp);

t.Field4 = row;

您通过拆分tmp创建了row,然后又将其重新加入。{1}}。避免仅使用row创建新字符串。

2)在方法结束时调用GC.Collect();以请求立即进行垃圾回收。这不会减少方法中使用的内存,但应该更快地释放内存。

答案 3 :(得分:-5)

如果您的应用程序对内存使用至关重要并且有大量重复数据,则应使用枚举替换字符串值。