C# 实际OOM和2GB对象OOM之间的差异?
我想知道在为实际的OOM(内存耗尽)抛出的OOM异常和在运行时抛出的异常之间是否有一些区别 我有以下导致OOM的代码(没有app.config更改,C# 实际OOM和2GB对象OOM之间的差异?,c#,exception,out-of-memory,C#,Exception,Out Of Memory,我想知道在为实际的OOM(内存耗尽)抛出的OOM异常和在运行时抛出的异常之间是否有一些区别 我有以下导致OOM的代码(没有app.config更改,gcAllowVeryLargeObjects默认设置为false): struct数据 { 双a; 双b; } //由于2GB对象限制,导致OOM。 列表a=新列表(134217725); //由于实际OOM而导致OOM。 列表b=新列表(); 对于(int i=0;i
gcAllowVeryLargeObjects
默认设置为false
):
struct数据
{
双a;
双b;
}
//由于2GB对象限制,导致OOM。
列表a=新列表(134217725);
//由于实际OOM而导致OOM。
列表b=新列表();
对于(int i=0;i<13421772;i++)
{
b、 增加(新数据[134217724]);
}
现在,我已经执行了Visual Studio中的代码,并得到以下异常:
- 2GB对象限制
System.OutOfMemoryException
HResult=0x8007000E
Message=引发了“System.OutOfMemoryException”类型的异常。
Source=mscorlib
堆栈跟踪:
at System.Collections.Generic.List`1..ctor(Int32容量)
在ConsoleApp1.Program.Main上(字符串[]args)
- 实际房间
System.OutOfMemoryException
HResult=0x8007000E
Message=引发了“System.OutOfMemoryException”类型的异常。
Source=ConsoleApp1
堆栈跟踪:
在ConsoleApp1.Program.Main上(字符串[]args)
从这里看来,这两个异常(堆栈跟踪/源除外)之间似乎没有显著差异
另一方面,我从LINQPad执行了完全相同的操作,得到了以下结果:
- 2GB限制
- 实际房间
RuntimeInformation.FrameworkDescription
将导致.NET Framework 4.8.4341.0
我的问题是关于检测/区分这两种情况,尽管我也很好奇为什么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);
}
}
对于调试
生成,您可以获得:
Exception of type 'System.OutOfMemoryException' was thrown.
Exception of type 'System.OutOfMemoryException' was thrown.
这意味着LINQPAD版本是RELEASE
,而visualstudio版本是DEBUG
所以答案是:是的,显然有一些区别,但是:
- 只有信息不同
- 我们不应该依赖这个永不改变的事实
- 它在
和DEBUG
版本之间有所不同RELEASE
旁白: 在我的电脑上,上面测试代码的
DEBUG
构建立即抛出两个OutOfMemoryException
异常
但是,发布版
构建会快速抛出第一个OutOfMemoryException
,但要过几秒钟才会抛出第二个异常。在此期间,它的内存使用量增加(根据任务管理器)
因此,很明显,至少对于.NETFramework4.8来说,还有其他一些不同之处。我没有在.Net 5或.Net Core上尝试过这个问题。除了学术好奇心之外,你对这个问题还有什么目的吗?VisualStudio和linqPad的目标是.net的哪些版本?发生和。元素数可能溢出并变为负值。嗯。@JonasH.net版本都是
.netframework4.8.4341.0
。我想知道不同的情况是否可以被检测到,因为它们代表了不同的状态:一个是无法帮助的(实际的OOM)并导致应用程序设计出现问题,而另一个(2GB大小限制)可以通过不同地处理单个数据结构来解决(如果可以检测到异常之间的差异,甚至可以在运行时进行)。您可以捕获OOM并按照您的建议(或我的理解方式)再次尝试分块分配。然后,OOM或work会再次失败。如果您运行的是32位代码,您可能还需要担心大型对象堆碎片。因此,在1Gb块失败的情况下,可以分配两个0.5Gb块。如果您需要处理对象,只需启用gcAllowVeryLargeObjects
,似乎更为合理。这就是助手,我希望异常包括它试图分配的内存量,因为这在调查异常时会很有用。谢谢,我没有想到DEBUG
和RELEASE
版本可能会对同一异常有不同的错误消息。我能够通过切换在VS中获得不同的错误消息为了发布
,尽管值得注意,我还必须针对特定的平台(不适用于发布
+任何CPU
)。
Exception of type 'System.OutOfMemoryException' was thrown.
Exception of type 'System.OutOfMemoryException' was thrown.