Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting an Out Of Memory Exception in my C# application?

My memory is 4G physical, but why I got out of memory exception even if I create just 1.5G memory object. Any ideas why? (I saw at the same time, in the performance tab of task manager the memory is not full occupied, and I could also type here -- so memory is not actually low, so I think I hit some other memory limitations)?

using System; using System.Collections.Generic; using System.Linq; using System.Text;  namespace TestBigMemoryv1 {     class MemoryHolderFoo     {         static Random seed = new Random();         public Int32 holder1;         public Int32 holder2;         public Int64 holder3;          public MemoryHolderFoo()         {             // prevent from optimized out             holder1 = (Int32)seed.NextDouble();             holder2 = (Int32)seed.NextDouble();             holder3 = (Int64)seed.NextDouble();         }     }      class Program     {         static int MemoryThreshold = 1500; //M         static void Main(string[] args)         {             int persize = 16;             int number = MemoryThreshold * 1000 * 1000/ persize;             MemoryHolderFoo[] pool = new MemoryHolderFoo[number];             for (int i = 0; i < number; i++)             {                 pool[i] = new MemoryHolderFoo();                 if (i % 10000 == 0)                 {                     Console.Write(".");                 }             }              return;         }     } } 
like image 513
George2 Avatar asked Feb 28 '09 04:02

George2


People also ask

What does system out of memory exception mean?

The OutOfMemoryException is a runtime exception that tells the programmer that there is no enough memory or there is a lack of contiguous memory for the allocations required by the C# program. To avoid this exception the user should always take necessary precautions and should handle this exception.

Can you catch an out of memory exception?

Sure, catching OutOfMemoryError is allowed. Make sure you have a plan for what to do when it happens. You will need to free up some memory (by dropping references to objects) before allocating any more objects, or you will just run out of memory again.


2 Answers

In a normal 32 bit windows app, the process only has 2GB of addressable memory. This is irrelevant to the amount of physical memory that is available.

So 2GB available but 1.5 is the max you can allocate. The key is that your code is not the only code running in the process. The other .5 GB is probably the CLR plus fragmentation in the process.

Update: in .Net 4.5 in 64 bit process you can have large arrays if gcAllowVeryLargeObjects setting is enabled:

On 64-bit platforms, enables arrays that are greater than 2 gigabytes (GB) in total size. The maximum number of elements in an array is UInt32.MaxValue.

<configuration>   <runtime>     <gcAllowVeryLargeObjects enabled="true" />   </runtime> </configuration> 
like image 125
JaredPar Avatar answered Oct 14 '22 02:10

JaredPar


Just additional to the other points; if you want access to a dirty amount of memory, consider x64 - but be aware that the maximum single object size is still 2GB. And because references are larger in x64, this means that you actually get a smaller maximum array/list size for reference-types. Of course, by the time you hit that limit you are probably doing things wrong anyway!

Other options:

  • use files
  • use a database

(obviously both has a performance difference compared to in-process memory)


Update: In versions of .NET prior to 4.5, the maximum object size is 2GB. From 4.5 onwards you can allocate larger objects if gcAllowVeryLargeObjects is enabled. Note that the limit for string is not affected, but "arrays" should cover "lists" too, since lists are backed by arrays.

like image 34
Marc Gravell Avatar answered Oct 14 '22 02:10

Marc Gravell