我想知道为实际OOM抛出的OOM异常(内存耗尽)和当达到2GB对象限制抛出的异常是否有什么区别。
我有以下导致OOM的代码(没有app.config更改,gcAllowVeryLargeObjects默认设置为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]);
}现在,我已经从Visual执行了代码,并得到了以下异常:
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)System.OutOfMemoryException
HResult=0x8007000E
Message=Exception of type 'System.OutOfMemoryException' was thrown.
Source=ConsoleApp1
StackTrace:
at ConsoleApp1.Program.Main(String[] args)从这里看,这两个异常(除了堆栈跟踪/源之外)似乎没有明显的区别。
另一方面,我从LINQPad中执行了完全相同的操作,得到了以下内容:


从两个地方执行RuntimeInformation.FrameworkDescription将导致.NET Framework 4.8.4341.0
我的问题是检测/区分这两种情况,尽管我也很好奇为什么LINQPad和VS执行之间的错误信息不同。
发布于 2021-03-05 14:04:08
我可以解释LinqPad和Visual之间的区别:
如果运行x86 DEBUG和RELEASE .Net Framework4.8,则生成以下代码:
static void Main()
{
try
{
List<Data> a = new List<Data>(134217725);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
try
{
List<Data[]> b = new List<Data[]>();
for (int i = 0; i < 13421772; i++)
{
b.Add(new Data[134217724]);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}对于RELEASE构建,您可以得到:
Array dimensions exceeded supported range.
Exception of type 'System.OutOfMemoryException' was thrown.对于DEBUG构建,您可以得到:
Exception of type 'System.OutOfMemoryException' was thrown.
Exception of type 'System.OutOfMemoryException' was thrown.这意味着LINQPAD版本为RELEASE,Visual版本为DEBUG。
所以答案是:是的,很明显有一些不同,但是:
DEBUG和RELEASE构建之间有所不同。撇开:
在我的PC上,上面测试代码的DEBUG构建立即抛出两个OutOfMemoryException异常。
然而,RELEASE构建会很快抛出第一个OutOfMemoryException,但在抛出第二个异常之前还需要几秒钟。在此期间,它的内存使用量增加(根据任务管理器)。
因此很明显,至少对于.Net Framework4.8,遮罩下还有其他一些不同之处。我还没有在.Net 5或.Net Core中尝试过这一点。
https://stackoverflow.com/questions/66493512
复制相似问题