C#Stringbuilder OutOfMemoryException

时间:2011-09-24 08:01:44

标签: c# out-of-memory stringbuilder

我写了以下功能

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());
  }
}

现在我想,这个字符串构建器有能力超过20亿字符(准确地说是2,147,483,647)。

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

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

1 个答案:

答案 0 :(得分:33)

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

相信 CLR(即使在64位系统上)也无法分配大小超过2GB的单个对象。 (这当然是这种情况。)我的猜测是你的StringBuilder试图加倍大小,并且超出了这个限制。通过构建具有特定容量的StringBuilder,您可以获得更高的收益 - 大约10亿的容量可能可行。

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


1 我认为StringBuilder的实现在.NET 4中实际上已经改变,在某些情况下使用片段 - 但我不知道细节。因此,在构建器形式中,总是可能不需要连续的内存...但是如果您曾调用过ToString,那么就会这样。