内存释放字符串构建器和c#中的d字节:内存不足exception

我正在研究c#。 我想知道如何释放stringbuilder n byte [] ….因为我在使用字符串生成器时遇到内存不足exception….另一件事是String.Replace()也给出了内存不足exception或者还有其他方法可以做同样的事情….请告诉我如何克服这些问题……提前谢谢

你建造了多大的弦? 你知道它会有多大吗? 如果是这样,设置StringBuilder的容量。

如果你不这样做,它开始时容量为16,然后每次突破该限制时加倍。 容量将为16,32,64,128。

每次执行此操作时,可能需要重新分配内存。

如果数据那么大,那么在文件流而不是StringBuilder中构建数据会更好吗?

如果您正在获得OOM,那么您需要保留太多数据。 听起来像你应该使用TextWriter (替换StringBuilder )或BinaryWriter / Stream (替换byte[] ) – 特别是StreamWriterFileStream (写入文件)。

例如:

 using (TextWriter dest = File.CreateText("out.txt")) { for (int i = 0; i < 100000; i++) { dest.Write(i); dest.Write(": "); dest.WriteLine(i % 5000); // why not } } 

像这样的基于流的API的优点是,一旦你编写了一个数据块,它就可以被垃圾收集等。

这是一些要试验的代码:

 using System; using System.Text; class Program { static void Main(string[] args) { StringBuilder sb = new StringBuilder(); try { //sb.Capacity = 690 * 1024 * 1024; while (true) sb.Append("asdf"); } catch (OutOfMemoryException) { Console.WriteLine("Died at: {0:N0} characters", sb.Capacity); Console.WriteLine("Memory used: {0:N0} bytes", GC.GetTotalMemory(false)); Console.ReadLine(); } } } 

在我的机器上输出(Win7 32位):

 Died at: 268,435,456 characters Memory used: 537,091,632 bytes 

32位操作系统提供了一个具有接近2千兆字节虚拟内存的进程。 正如您所看到的,示例程序很好地消失了,只消耗了25%。 问题是虚拟内存地址空间碎片。 可用的2千兆字节需要存储代码和数据。 您可以通过SysInternal的VMMap实用程序深入了解VM的划分方式。

关于StringBuilder的工作原理,您可以对此做些什么。 它使用内部数组来存储字符串。 根据需要重新分配此数组以存储不断增长的字符串,每次将大小加倍。 Capacity属性告诉您该数组的大小。

这会导致另一种碎片,堆碎片。 在数组大小加倍之后,可以收集旧数组,但会生成一个“空闲块”,该块不能合并回来以便可用于大型连续分配。 这是大对象堆和Windows堆管理器的实现细节,谷歌“后备缓存”以了解更多信息。

一种解决方法是在虚拟内存空间碎片化之前快速吞噬虚拟内存空间。 工作中删除评论以查看此信息。 在我的机器上:

 Died at: 723,517,440 characters Memory used: 1,447,256,944 bytes 

我通过实验微调了容量值,您可能必须这样做才能使它在您的机器上运行。 差异非常大,差不多是原来的3倍。 请注意,这在实际程序中不太可能再现良好,时机至关重要。 或者在另一台机器上,一定要保持在截止点以下。 实际上,一旦你使用的缓冲区超过1.34亿个字符,你就会冒OOM的风险。