.NET框架如何为OutOfMemoryException分配内存?

RX_*_*_RX 144 .net c# out-of-memory

在C++中,实际上可以通过值抛出异常而无需在堆上分配内存,因此这种情况很有意义.但在.NET框架中OutOfMemoryException是一种引用类型,因此它是在堆上分配的.OutOfMemoryException当没有足够的内存来创建新对象时,.NET框架如何分配内存?

Bri*_*sen 163

它由运行时预先分配.如果您浏览任何托管进程的堆,您将找到该异常的实例.

以下是Hello World应用程序的预分配异常:

0:003> !dumpheap -stat -type Exception
Statistics:
      MT    Count    TotalSize Class Name
735f2920        1           84 System.ExecutionEngineException
735f28dc        1           84 System.StackOverflowException
735f2898        1           84 System.OutOfMemoryException
735f2744        1           84 System.Exception
735f2964        2          168 System.Threading.ThreadAbortException
Run Code Online (Sandbox Code Playgroud)

  • 运行时不必使用与代码相同的规则.另一个例子是,如果抛出`StackOverflowException`就可以捕获它,但是如果运行时抛出该异常,则无法捕获它(默认情况下). (36认同)
  • CLR的许多底层机制实际上是用"C"和"C++"编写的.因此,完全有可能对象是"新到位"或者内存被操纵. (8认同)
  • 如果需要两个具有相同类型的异常,因为两个线程同时抛出它们会怎么样? (7认同)
  • 但是调用了[OutOfMemoryException`]的构造函数(http://referencesource.microsoft.com/#mscorlib/system/outofmemoryexception.cs,5ad855b434264d4b,references). (4认同)
  • @hvd有什么副作用?OOM是否提供堆栈跟踪?虽然剩下的信息是相当静态的,但我会这样做? (2认同)

Ran*_*832 42

当在运行时内遇到内存不足的情况时,它会调用ThrowOutOfMemory.这会调用Exception :: GetOOMException,它构造堆栈上的对象,然后将其复制到静态分配的全局实例,然后抛出该实例.

这不是托管的异常,但它是在ex.h中声明的C++异常.C++异常在clrex.cpp中转换为托管异常,其中包含专门抛出预先分配的托管 OutOfMemoryException的代码,该异常最初是在appdomain.cpp中分配和构造的.

注意:其中一些源文件很大,可能会在加载语法突出显示时将浏览器挂起几秒钟.

Tim Schmelter在对另一个答案的注释中链接的调用站点与运行时内存不足和无法构造对象无关.