C#Stringbuilder OutOfMemoryException

我写了以下function

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

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

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

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

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

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

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


1我认为StringBuilder的实现在.NET 4中实际上已经改变,在某些情况下使用片段 – 但我不知道细节。 因此,在构建器forms中,它可能并不总是需要连续的内存……但是如果你曾经调用过ToString ,那就好了。