简单的c#数组抛出OutOfMemory异常

本文关键字:OutOfMemory 异常 数组 简单 | 更新日期: 2023-09-27 18:17:32

我有一个相当大、相当简单的数组,它跟踪750,000个条目。在64位的。net中它工作得很好;然而,在32位客户端它失败与OutOfMemory异常。我知道我没有耗尽内存。需要此程序的客户端无法使用64位版本。

以下伪代码编译(edit:原始代码没有编译,由于拼写错误,这已经修复),并抛出相同的异常,当针对x86架构时,两台机器:

  • Windows XP, 32位机器,运行4gb内存和。net Framework 4
  • Windows 7, 64位机器,运行8gb内存和。net Framework 4

Edit:将编译器标志显式地切换到以针对x64架构,允许它在Windows 7, 64位机器上运行。

using System;
public class Storage
{
    Storage futureStorage;
    int count;
    int years;
    bool isTest;
    bool isSet;
}
public static class Program
{
    public static void Main()
    {
        Storage[] storageArray = new Storage[750000];
        for (int i = 0; i < 750000; i++)
        {
            storageArray[i] = new Storage();
        }
    }
}


编辑:

这个代码运行的网络是一个封闭的网络,没有外部网络连接,所以发布更准确的代码和相关的异常细节是我正在研究的一个过程。我确实有智能运行,具有完整的调试符号和一些编译器开关,一旦我将其移植到互联网连接的网络,就会有更多细节。


在两台机器上,代码的索引都是693,000 (XP是693,002,Windows 7是693,646)。

有人知道是什么问题吗?当我在代码之后执行转储和配置文件时,我几乎没有使用25 MB的RAM。

如果它能给我买到任何东西,我会切换到不安全/非管理的,但是我唯一的尝试使我无法使用我的Storage类。

更新:

似乎有几个人无法复制这个问题(包括我自己在不同的机器/网络上)。

然而,我想出了一个解决方案(使用LINQ),缓解了这个问题,它现在只抛出异常1/5次左右,有人知道是否有任何问题或警告,我应该意识到使用这个解决方案,为什么内部它可能比另一个工作?

using System;
using System.Linq;    
public class Storage
{
    Storage futureStorage;
    int count;
    int years;
    bool isTest;
    bool isSet;
}
public static class Program
{
    public IEnumerable<Storage> storageEnumerable;
    public static void Main()
    {
        storageEnumerable = (from x in  Enumerable.Range(0, 750000) select new Storage() {count = x});
        foreach (Storage s in storageEnumerable)
            Console.WriteLine(x);
    }
}

上面的LINQ代码使用的内存少得多,但是异常仍然发生;并且只能在这个网络中的机器上,而不能在网络之外的其他机器上(或者在IIS应用程序池中)。

考虑到其他用户已经报告无法重现错误,这似乎可能是环境或硬件特定的。是否有网络监控工具或反病毒程序触发这两个代码实现?如果是这样,是否有更好的/推荐的方法来初始化数组,以便我避免这种情况?

简单的c#数组抛出OutOfMemory异常

也许这会有帮助?

数组的最大容量是多少?

答案说也许使用List可以使用更少的内存

在没有更多调试信息的情况下,我猜测您的程序使用了虚拟内存。使用任务管理器查看所有已使用的内存,您必须将这些字段添加到进程资源管理器中。

根据记录,来自Jeffrey Richter(线程工作章节):

一个32位进程最多有2gb的可用地址空间。在加载了一堆Win32 dll,加载了CLR dll,分配了本机堆和托管堆之后,大约有1.5 GB的地址空间剩余。

尝试创建更多线程将导致抛出OutOfMemoryException。

当然,64位进程提供8tb的地址空间,因此理论上可以创建数十万个线程

初始化数组后,可用的空间越来越少。在某个时刻,你没有空的内存,你得到了你的OutOfMemoryException

我认为LINQ的使用更明智地利用了资源,并且在某些情况下它可以正常工作。

很遗憾,你不能用它做很多事情,很抱歉。你唯一能做的就是

  • 不要在数组中使用太多的对象
  • 更频繁地使用GC.Collect来收集不再使用的对象

尝试使您的存储struct而不是class值类型数组比引用类型数组消耗的内存少