C#Stringbuilder OutOfMemoryException

Atu*_*tur 18 c# stringbuilder out-of-memory

我写了以下功能

public void TestSB()
{
  string str = "The quick brown fox jumps over the lazy dog.";
  StringBuilder sb = new StringBuilder();
  int j = 0;
  int len = 0;

  try
  {
     for (int i = 0; i < (10000000 * 2); i++)
     {
        j = i;
        len = sb.Length;
        sb.Append(str);
     }

    Console.WriteLine("Success ::" + sb.Length.ToString());
  }
  catch (Exception ex)
  {
      Console.WriteLine(
          ex.Message + " :: " + j.ToString() + " :: " + len.ToString());
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我想,这个stringbuilder有能力超过20亿字符(准确地说是2,147,483,647).

但是当我运行上面的函数时,它只是在达到大约8亿的容量时给出了"System.OutOfMemoryException".而且,我在具有相同内存和相似负载量的不同PC上看到了截然不同的结果.

任何人都可以提供或解释我的原因.

Jon*_*eet 34

每个字符需要2个字节(因为char在.NET中是UTF-16代码单元).所以当你达到8亿个字符时,需要1.6GB的连续内存1.现在当StringBuilder需要自己调整大小时,它必须创建另一个新大小的数组(我相信它会尝试将容量加倍) - 这意味着尝试分配一个3.2GB的数组.

相信 CLR(即使在64位系统上)也无法分配超过2GB大小的单个对象.(当然情况确实如此.)我的猜测是你StringBuilder试图将尺寸增加一倍,然后超出限制.通过构建StringBuilder具有特定容量的产品,您可以获得更高的价值- 大约10亿的容量可能是可行的.

在正常的过程中,这当然不是问题 - 即使是需要数百兆的弦也很少见.


1我相信StringBuilder在.NET 4 中实际更改的实现在某些情况下使用片段 - 但我不知道细节.因此,在构建器形式的情况下,它可能并不总是需要连续的内存......但是如果你曾经打过电话就会这样ToString.

  • @Tigran我认为因为StringBuilder有效地需要**连续的**内存来分配它的内容,并且内存可以根据机器事先做的事情以不同的方式进行分段.当可能仍有大量物理RAM仍然空闲时,你仍然可能得到OutOfMemory异常,因为没有足够的*连续*内存. (2认同)