解决方案 »

  1.   

    2GB是32位程序的最大地址空间。
    但一部分地址是系统占用了,
    你的程序本身再用去一部分,
    其他相关DLL(例如NET平台)又去一部分,最后可供你使用的,大约就是1.5G
      

  2.   

    OutOfMemory是内存溢出,不代表内存真的不足
    你可以执行如下简单代码测试:
    int[,] i=new int[20000,20000];
      

  3.   

    .net 有大量的代码会抛出这个信息。.net分配的地址是随时可能浮动于物理地址之上的,可能根本上少于或者多于全部物理地址,应用程序的memory就好像到酒店开房,可能是单人间、双人间、套房、总统套、会议室、宴会厅,等等。随用随向.net申请,是动态递增的,所以你会看到进程所占的总 memory 数字可能随着使用时间而过一段时间翻倍扩大,但是通常都不会减小的。 memory 跟物理地址并没有对应关系,只是看每种 .net 对象的底层“规范上”要求的最大数值是否达到而已。一些会一点c++的人总是把这个异常联系到物理内存大小上,这可真是一个杯具的事情。比如说你声明一个对象 StringBuilder sb = new StringBuilder(0, 15); 然后你插入一些字符,一旦超过15个字符,就抛出 OutofMemory 异常了。你不能说“整个机器的物理内存只有15个字符”吧?
      

  4.   

    整个 .net 类库,都不知道物理内存有多大。真正当底层发现“物理内存+虚拟内存都没有了“的时候,你的程序就收不到这个异常。凡是抛出这个异常,这个异常是.net 类库定义的、类库设计人员专门给你抛出的异常,99.9%的情况下都不需要从“物理内存是否够用”角度去看这个异常。
      

  5.   

    对于你的程序,如果你换到 64 为系统下,同样是2G内存,可能你就要等上20分钟才可能抛出异常。因为 64 位系统应该允许你创建并同时并发几万个 Thread 对象,而不是1千个。
      

  6.   

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx
    The number of threads a process can create is limited by the available virtual memory. By default, every thread has one megabyte of stack space. Therefore, you can create at most 2,048 threads. If you reduce the default stack size, you can create more threads. However, your application will have better performance if you create one thread per processor and build queues of requests for which the application maintains the context information. A thread would process all requests in a queue before processing requests in the next queue.
      

  7.   

    这样开线程占用的内存不属于working set,你可以打印当前进程的 VirtualMemorySize64 属性看这个内存增长,会看到这样子确实差不多到了2G的时候out of memory想看更详细的内存占用,可以使用sysinternals的工具VMMap,可以看到大量内存被Stack项占用,也就是分配给线程的栈。
      

  8.   

    2^32=4G不应该使用线程测试,而应该不断地申请内存,直到内存溢出。
    这用c++很容易实现,不断new数组就行了。然后就会看到,任务管理器中的debug程序进程占用的内存迅速上升,直到2G多
      

  9.   

    关于这类系统资源限制,可以看sysinternals的作者写的一系列文章:
    http://blogs.technet.com/b/russinovich/archive/2009/07/08/3261309.aspx