I was wondering if there is some difference between the OOM exceptions thrown for an actual OOM (memory runs out), and the exception thrown when the 2GB object limit is hit?
I have the following code for causing the OOMs (no app.config changes, gcAllowVeryLargeObjects
is by default set to false
):
struct Data
{
double a;
double b;
}
// Causes OOM due to the 2GB object limit.
List<Data> a = new List<Data>(134217725);
// Causes OOM due to actual OOM.
List<Data[]> b = new List<Data[]>();
for (int i = 0; i < 13421772; i++)
{
b.Add(new Data[134217724]);
}
Now, I've executed the code from Visual Studio, and I get the following exceptions:
- 2GB object limit
System.OutOfMemoryException
HResult=0x8007000E
Message=Exception of type 'System.OutOfMemoryException' was thrown.
Source=mscorlib
StackTrace:
at System.Collections.Generic.List`1..ctor(Int32 capacity)
at ConsoleApp1.Program.Main(String[] args)
- actual OOM
System.OutOfMemoryException
HResult=0x8007000E
Message=Exception of type 'System.OutOfMemoryException' was thrown.
Source=ConsoleApp1
StackTrace:
at ConsoleApp1.Program.Main(String[] args)
From here, it doesn't seem like there is a significant difference between the two exceptions (other than the stack trace/source).
On the other hand, I executed the exact same thing from LINQPad and got the following:
- 2GB limit
- actual OOM
Executing RuntimeInformation.FrameworkDescription
from both places results in .NET Framework 4.8.4341.0
My question is about detecting/differentiating between the two cases, although I am also curious as to why the error messages differ between the LINQPad and VS executions.