繁体   English   中英

StringBuilder 类 OutOfMemoryException

[英]StringBuilder Class OutOfMemoryException

我写了以下功能

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 中更改为在某些情况下使用片段 - 但我不知道细节。 因此,它可能并不总是在仍处于构建器形式时需要连续内存......但如果你曾经调用ToString它会。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM