使用插入()和清除时,内存泄漏的StringBuilder() [英] Memory Leak in StringBuilder when using Insert() and Clear()

查看:3283
本文介绍了使用插入()和清除时,内存泄漏的StringBuilder()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些行添加到一个StringBuilder,其中该线最后加入应在字符串的开头和最老末。我想补充一个新的生产线是这样的:

I need to add some lines to a StringBuilder, where the line added last should be at the beginning of the string and the oldest at the end. I add a new line like this:

stringBuilder.Insert(0, "Some text." + Environment.NewLine);

一旦这样做,我空了StringBuilder的是这样的:

Once done, I empty the StringBuilder like this:

stringBuilder.Clear();

予重复使用相同的StringBuilder多次,这导致随着时间的推移出现内存异常。

I reuse the same StringBuilder many times, which leads to an Out of Memory exception over time.

我调查与下面的测试程序,这表明当使用追加()和清除(),所述的StringBuilder的容量保持相同的问题,这是无论使用多少次。但是,当使用插入()和Clear(),StringBuilder的容量不断增加。以下是测试结果:

I investigated the problem with the test program below, which shows that when using Append() and Clear(), the Capacity of the StringBuilder stays the same, regardless how many times it is used. But when using Insert() and Clear(), the Capacity of the StringBuilder keeps growing. Here are the test results:

           stringbuilder.Capacity
Iteration  Append Insert
0:         81984,  78016
1:         81984, 155938
2:         81984, 233860
3:         81984, 311782
4:         81984, 389704
5:         81984, 467626
6:         81984, 545548
7:         81984, 623470
8:         81984, 701392

这些测试数字是从下面的测试程序。如可以看到的,1无论多少次不追加()和清除(),容量不改变。但它确实继续使用插入()和Clear()当越来越多。

These test figures are from the test program below. As one can see, regardless how many times one does Append() and Clear(), the capacity does not change. But it does keep growing when using Insert() and Clear().

问:是不是正确的说,StringBuilder的有内存泄漏使用插入()和Clear()时,因为容量不断增加,这最终导致了内存不够的异常?

Question: Is it correct to say that StringBuilder has a memory leak when using Insert() and Clear(), because the Capacity keeps growing and this finally leads to an Out Of Memory exception ?

要测试它自己,只是增加了上限outerIndex得到例外。

To test it for yourself, just increase the upper limit for outerIndex to get the exception.

如果这的确应该被视为一个内存泄漏,我该如何将它报告给微软?

If this should indeed be considered a memory leak, how do I report it to Microsoft ?

using System;
using System.Text;

namespace TestStringBuilder {
  class Program {
    static void Main(string[] args) {
      StringBuilder stringBuilderAppend = new StringBuilder();
      StringBuilder stringBuilderInsert = new StringBuilder();
      string capacityGrow = "";
      for (int outerIndex = 0; outerIndex < 9; outerIndex++) {
        for (int innerIndex = 0; innerIndex < 1000; innerIndex++) {
          stringBuilderAppend.Append("Just some text to fill stringbuffer with 01234567890qwertyuiopasdfghjklzxcvbnm");
          stringBuilderInsert.Insert(0, "Just some text to fill stringbuffer with 01234567890qwertyuiopasdfghjklzxcvbnm");
        }
        stringBuilderAppend.Clear();
        stringBuilderInsert.Clear();
        capacityGrow += outerIndex + ": " + stringBuilderAppend.Capacity + ", " + stringBuilderInsert.Capacity  + Environment.NewLine;
      }
      //check in the debugger capacityGrow to see the capacity used in each iteration
      System.Diagnostics.Debugger.Break();
    }
  }
}

EDIT1: 一些更多的搜索后,我发现的建议清除(后设置容量为0),像这样的:

After some more searching, I found the suggestion to set Capacity to 0 after Clear(), like this:

stringBuilder.Clear();
stringBuilder.Capacity = 0;

这prevents内存泄漏并导致内存溢出异常使用插入(时)反复,但它也违背了重用StringBuilder的,这是prevent分配和内存释放来实现的目的更高的速度。相反,设置容量= 0时,人们可以同时只使用一个新的StringBuilder,而不是清除()。

This prevents the memory leak and resulting Out of Memory exception when using Insert() repeatedly, but it also defeats the purpose of reusing the StringBuilder, which is to prevent allocation and deallocation of memory to achieve a higher speed. Instead to set Capacity=0, one could as well just use a new StringBuilder instead of Clear().

似乎插入()不重用已经分配到StringBuilder未使用的存储器,但不断增加新的存储器,尽管清除()。我还是觉得这是一个错误,因为谁也期望耗尽内存,尽管清除的StringBuilder?我想AP preciate一些意见,如果这是一个错误,如果它应该报告给微软。

It seems that Insert() is not reusing the unused memory assigned already to the StringBuilder, but keeps adding new memory, despite the Clear(). I still feel this is a bug, because who would expect to run out of memory despite clearing the StringBuilder ? I would appreciate some comments if this is a bug and if it should be reported to Microsoft.

EDIT2: 我报告错误给微软: https://connect.microsoft.com/VisualStudio/feedback/details/1242873

I reported the bug to Microsoft on: https://connect.microsoft.com/VisualStudio/feedback/details/1242873

请按照链接和upvote错误,否则我担心微软会不会考虑它: - (

Please follow the link and upvote the bug, otherwise I fear Microsoft will not look into it :-(

结束语:

  • 从previous贴子我做的体验,评论者快说有我的程序有问题。他们评论则相当粗暴,哪怕是他们谁是错的。

  • From previous postings I made the experience that commenters quickly say there is a problem in my program. They comment then quite rudely, even if it is them who are wrong.

从previous贴子我做的体验,评论者要标记一个问题,这个问题已经有答案,仅仅是因为他们不明白我的问题与其他问题之间的区别。事实上,有很多回答问题的stackoverlow的StringBuilder的和内存不足。我读了所有我能找到与谷歌或stackoverlow。他们的关于append()和大约极长的文本。他们不会将()。请注意,使用附加()时,会出现即使使用插入()很短的字符串,只有当我的问题,而不是!

From previous postings I made the experience that commenters like to mark a question as "This question already has an answer", just because they don't understand the difference between my question and the other questions. Indeed, there are many answered questions on stackoverlow for StringBuilder and Out of Memory. I read all I could find with google or stackoverlow. They are about APPEND() and about EXTREMELY long texts. They are not about Insert(). Please note that my problems occurs even with very short strings and only when using Insert(), but not when using Append() !

从previous贴子我做的体验,评论者喜欢建议使用不同的编程,如避免使用插入(),并通过追加和增加在反序行解决问题。虽然这可能是可能在某些情况下,我觉得将()和Clear()应该工作正常,我们应该让微软知道,如果出现了问题。

From previous postings I made the experience that commenters like to suggest to use different programming, like avoiding using Insert() and solve the problem by using Append and adding the lines in inverted sequence. While this might be possible in some cases, I feel that Insert() and Clear() should work properly and we should Microsoft let know if there is a problem.

推荐答案

我会说该行为是可以预料的:

I would say that the behaviour is to be expected:

Clear()

该文档的状态:

The doc states:

删除所有字符从当前StringBuilder实例。[...]   调用清除方法不会修改当前实例的能力或MAXCAPACITY财产。的看Documenation

Removes all characters from the current StringBuilder instance.[...] Calling the Clear method does not modify the current instance's Capacity or MaxCapacity property.see Documenation

所以清除()删除内容但保留内存中分配。

So Clear() removes the content but keeps the memory allocated.

Insert()

下面的文档规定,previous内容被移位,并根据需要调整的能力。 ( DOC )这不是完全清楚,但是我认为新的内存容量+新长度分配剩下的复制。现在。这未必是最佳的解决方案,但我想,这是它的实现方式。所以内存不足的情况​​是可以预料的。

Here the doc states that the previous content is shifted and the capacity adjusted as needed. (doc) This is not completely clear, but I assume that new memory capacity + new length is allocated and the rest copied over. Now. this may not be the optimal solution, but I figure that this is the way it is implemented. So the out-of-memory situation is to be expected.

另外一个建议:一定要在第一位置插入是 - 无论执行 - pretty的昂贵。如果你需要的结果只有一次考虑使用名单,其中,串&GT; 在其中插入新行位置0,然后遍历列表一次,并建立字符串

Another suggestion: Always inserting at the first position is - regardless of the implementation - pretty expensive. If you need the result only once consider using a List<string> where you insert the new lines at position 0 and then iterate over the list once and build the string.

编辑:

在看的(假设)的我觉得的StringBuilder 确实allocatign为块的每一次插入一个新的实例 - 无论任何其他罗姆可用。 我跟着来电降至 MakeRoom 其中,在行2044年一个新的块分配。

After looking at the (assumed) source I think that StringBuilder is indeed allocatign a new instance as 'chunk' for every insert - regardless of any other romm available. I followed the calls down to MakeRoom where at line 2044 a new chunk is allocated.

这篇关于使用插入()和清除时,内存泄漏的StringBuilder()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆