实际 OOM 和 2GB 对象 OOM 之间的区别?
Difference between actual OOM and 2GB object OOM?
我想知道为实际 OOM(内存耗尽)抛出的 OOM 异常与 2GB object limit is hit?
时抛出的异常之间是否存在某些差异
我有以下导致 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 Studio 中的代码,但出现以下异常:
- 2GB 对象限制
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)
- 实际 OOM
System.OutOfMemoryException
HResult=0x8007000E
Message=Exception of type 'System.OutOfMemoryException' was thrown.
Source=ConsoleApp1
StackTrace:
at ConsoleApp1.Program.Main(String[] args)
从这里看来,这两个异常之间似乎没有显着差异(除了堆栈 trace/source)。
另一方面,我从 LINQPad 执行了完全相同的操作并得到以下结果:
- 2GB 限制
- 实际 OOM
从两个地方执行 RuntimeInformation.FrameworkDescription
导致 .NET Framework 4.8.4341.0
我的问题是关于这两种情况之间的 detecting/differentiating,尽管我也很好奇为什么 LINQPad 和 VS 执行之间的错误消息不同。
我可以解释一下LinqPad和Visual Studio的区别:
如果您 运行 x86 DEBUG
和 RELEASE
.Net Framework 4.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 Studio版本是DEBUG
。
所以答案是:是的,显然有一些不同,但是:
- 只有消息不同
- 我们不应该依赖这个一成不变的
DEBUG
和 RELEASE
版本不同。
旁白:
在我的电脑上,上述测试代码的 DEBUG
构建立即抛出两个 OutOfMemoryException
异常。
然而,RELEASE
构建很快抛出第一个 OutOfMemoryException
,但在它抛出第二个异常之前几秒钟。在此期间,其内存使用量增加(根据 任务管理器)。
很明显,引擎盖下还有一些其他差异,至少对于 .Net Framework 4.8 而言。我还没有用 .Net 5 或 .Net Core 尝试过。
我想知道为实际 OOM(内存耗尽)抛出的 OOM 异常与 2GB object limit is hit?
时抛出的异常之间是否存在某些差异我有以下导致 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 Studio 中的代码,但出现以下异常:
- 2GB 对象限制
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)
- 实际 OOM
System.OutOfMemoryException
HResult=0x8007000E
Message=Exception of type 'System.OutOfMemoryException' was thrown.
Source=ConsoleApp1
StackTrace:
at ConsoleApp1.Program.Main(String[] args)
从这里看来,这两个异常之间似乎没有显着差异(除了堆栈 trace/source)。
另一方面,我从 LINQPad 执行了完全相同的操作并得到以下结果:
- 2GB 限制
- 实际 OOM
从两个地方执行 RuntimeInformation.FrameworkDescription
导致 .NET Framework 4.8.4341.0
我的问题是关于这两种情况之间的 detecting/differentiating,尽管我也很好奇为什么 LINQPad 和 VS 执行之间的错误消息不同。
我可以解释一下LinqPad和Visual Studio的区别:
如果您 运行 x86 DEBUG
和 RELEASE
.Net Framework 4.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 Studio版本是DEBUG
。
所以答案是:是的,显然有一些不同,但是:
- 只有消息不同
- 我们不应该依赖这个一成不变的
DEBUG
和RELEASE
版本不同。
旁白:
在我的电脑上,上述测试代码的 DEBUG
构建立即抛出两个 OutOfMemoryException
异常。
然而,RELEASE
构建很快抛出第一个 OutOfMemoryException
,但在它抛出第二个异常之前几秒钟。在此期间,其内存使用量增加(根据 任务管理器)。
很明显,引擎盖下还有一些其他差异,至少对于 .Net Framework 4.8 而言。我还没有用 .Net 5 或 .Net Core 尝试过。