C# 实际OOM和2GB对象OOM之间的差异?

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

我想知道在为实际的OOM(内存耗尽)抛出的OOM异常和在运行时抛出的异常之间是否有一些区别

我有以下导致OOM的代码(没有app.config更改,
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.