代码之家  ›  专栏  ›  技术社区  ›  Andrew

内存不足异常

  •  2
  • Andrew  · 技术社区  · 16 年前

    我有一个非常需要内存的应用程序。它在一些大数组中保存大量数据。

    我最近注意到了偶尔的记忆缺失。在我的应用程序(ASP.NET)用完800MB可用内存之前,就会发生这些内存不足的异常。 我已经将这个问题追踪到代码区域,在那里数组被调整了大小。数组包含大小为74字节的结构。(我知道您不应该创建大于16字节的结构),但此应用程序是来自vb6应用程序的端口)。我已经尝试将结构改为类,这似乎已经解决了这个问题。

    我认为改变类解决问题的原因与这样一个事实有关:当使用一个结构并调整数组的大小时,无法找到一段足够大的内存来存储新数组(例如(currentArraySize+increaseBySize)*74)。这会导致内存不足异常。

    类不是这样的,因为数组的每个元素只需要8字节就可以存储指向新对象的指针。

    我的想法对吗?

    4 回复  |  直到 11 年前
        1
  •  2
  •   Mikael Svenson    16 年前

    当您调整数组的大小时,它将创建一个新的数组来保存新的数据,然后复制到数据上,同时在内存中有两个相同数据的副本。如你所料。

    使用结构时,数组将占用 struct size * number of elements . 使用类时,它将只包含指针。

    同样的情况也适用于随着时间推移而增大的列表,因此用预期的项目数初始化它是明智的,以避免调整大小和复制。

    如您所知,在32位系统上,您将在大约800MB的内存中命中。您可以尝试的一种解决方案是将结构放到磁盘上,并在需要时读取它们。因为它们是固定大小的,所以您可以很容易地跳到文件的正确位置。

    我有一个项目 Codeplex 用于处理大量数据。它有一种可能自动增长的数组类型,如果您再次在内存中保存它时遇到问题,这可能会帮助您的场景。

        2
  •  3
  •   Brian Rasmussen    16 年前

    关于数组存储方式的假设是正确的。从结构改为类会给每个实例增加一点开销,并且您将失去位置的优势,因为所有数据都必须通过引用收集,但是正如您观察到的,它现在可以解决内存问题。

        3
  •  2
  •   Ian Mercer    16 年前

    您遇到的问题可能是由于大型对象堆的碎片而不是正常的内存不足情况(所有内存都已耗尽)。

    http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

    该解决方案可能与通过大的固定增量而不是小的随机增量来增加数组一样简单,这样当数组被释放时,LOH内存块可以重新用于新的大数组。

    这也可以解释结构->类问题,因为结构可能存储在数组本身中,而类将是小对象堆中的小对象。

        4
  •  0
  •   Community Mohan Dere    9 年前

    .NET框架4.5.1能够在垃圾收集期间显式压缩大型对象堆(LOH)。

    GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
    GC.Collect();
    

    更多信息请参见: GCSettings.LargeObjectHeapCompactionMode

    还有一个问题: Large Object Heap Compaction, when is it good?

    推荐文章