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

时间:2011-12-12 22:39:54

标签: c# .net arrays out-of-memory

我有一个相当大,相当简单的数组,它跟踪750,000个条目。在64位.NET中它运行良好;但是在32位客户端上,它失败了OutOfMemory异常。我知道我的记忆力不足。需要此程序的客户端,不能使用64位版本。

以下伪代码编译(编辑:原始代码编译由于拼写错误,已修复)并且在定位时抛出相同的异常x86架构,在两台机器上:

  • Windows XP,32位计算机,运行4 GB RAM和.NET Framework 4
  • Windows 7,64位计算机,运行8 GB RAM和.NET Framework 4

编辑:将编译器标志切换为显式以定位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();
        }
    }
}

<小时/> 修改

此代码运行的网络是一个封闭的网络,没有外部网络连接,因此发布更精确的代码和相关的异常详细信息更多的是我正在处理的过程。我确实有intellitrace运行,有完整的调试符号和一些编译器开关,一旦我将它移植到互联网连接网络,就会有更多细节。


在这两台机器上,代码在693,000的索引周围爆炸(在XP上为693,002,在Windows 7上为693,646)。

任何人都对这个问题有什么想法?当我在代码之后进行转储和配置文件时,我几乎不使用25 MB的RAM。

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

更新

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

然而,我提出了一个解决方案(使用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应用程序池中)。

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

4 个答案:

答案 0 :(得分:1)

我的猜测没有更多的调试信息是你的程序使用虚拟内存。使用taskmanager探索所有使用的内存,你必须将这些字段添加到进程资源管理器中。如果这是cae,你实际上会耗尽内存。

答案 1 :(得分:1)

来自Jeffrey Richter(线程工作章节)的记录:

  

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

     

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

     

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

因此,在初始化阵列后,可用空间越来越少。在某些时刻,你没有空记忆,你得到了OutOfMemoryException

我认为LINQ的使用更明智地使用资源,并且在某些时候它可以正常运行。

不幸的是,你不能做很多事情,抱歉。你唯一能做的就是

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

答案 2 :(得分:1)

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

答案 3 :(得分:1)

也许这会有所帮助?

What is the Maximum Size that an Array can hold?

答案是说使用List可能会使用更少的内存。