¿Cómo asigna .NET Framework la memoria para OutOfMemoryException?

144

En C ++ es posible lanzar una excepción por valor sin asignar memoria en un montón, por lo que esta situación tiene sentido. Pero en .NET framework OutOfMemoryExceptiones un tipo de referencia, por lo tanto, se asigna en un montón. ¿Cómo asigna .NET Framework la memoria para OutOfMemoryExceptioncuando no hay suficiente memoria para crear un nuevo objeto?

RX_DID_RX
fuente
66
Excelente pregunta Tal vez se reserva suficiente memoria solo para esa situación.
GreatAndPowerfulOz
19
Solo para agregar a las otras respuestas que ya están aquí, tenga en cuenta que OOM significa que el bloque que solicitó no se puede asignar. Si solicita 100Mb y el bloque más grande disponible que puede encontrar el tiempo de ejecución es solo 99Mb, fallará. Pero una excepción OOM solo necesita unos pocos bytes de memoria. Entonces, solo porque su asignación falló no significa que no quede memoria cero. Pero, por supuesto, es probable que el tiempo de ejecución reserve algo de memoria para cubrirse en esta situación
Jason Williams
44
Su suposición sobre C ++ es incorrecta, por cierto. Dependiendo del compilador, es posible que se asignen excepciones en el montón. El compilador de MS no lo hace, pero en Common C ++ ABI, las excepciones se asignan en el montón, excepto que hay un pequeño búfer de emergencia preasignado que se usará en su lugar si no queda espacio en el montón.
Sebastian Redl

Respuestas:

163

Está preasignado por el tiempo de ejecución. Si explora el montón de cualquier proceso administrado, encontrará una instancia de esa excepción.

Estas son las excepciones preasignadas de una aplicación 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
Brian Rasmussen
fuente
44
Pero el constructor deOutOfMemoryException se llama.
Tim Schmelter
36
El tiempo de ejecución no tiene que jugar con las mismas reglas que su código. Otro ejemplo es que si lanzas StackOverflowExceptionpuedes atraparlo, pero si el tiempo de ejecución arroja esa excepción, no puedes atraparlo (por defecto).
Brian Rasmussen
8
Gran parte de los mecanismos subyacentes del CLR en realidad están escritos en "C" y "C ++". Por lo tanto, es completamente posible que el objeto esté "nuevo en su lugar" o que la memoria sea manipulada de otra manera.
GreatAndPowerfulOz
2
@hvd ¿Cuál es el efecto secundario? ¿OOM da un seguimiento de la pila? ¿Hubiera pensado que el resto de la información es bastante estática?
James Barrass
77
¿Qué pasa si se requieren dos excepciones de aquellos con el mismo tipo porque dos hilos los lanzan al mismo tiempo?
Traubenfuchs
42

Cuando se encuentra una condición de falta de memoria dentro del tiempo de ejecución, llama a ThrowOutOfMemory . Esto llama Exception :: GetOOMException , que construye el objeto en la pila y luego lo copia en una instancia global asignada estáticamente, que luego se arroja.

Esta no es la excepción conseguido, sin embargo, una excepción de C ++ declaró en ex.h . Las excepciones de C ++ se convierten en excepciones administradas en clrex.cpp , que contiene código para lanzar específicamente la excepción OutOfMemoryException administrada previamente asignada, que originalmente se asignó y construyó en appdomain.cpp .

Nota: Algunos de estos archivos de origen son grandes y pueden colgar su navegador durante varios segundos mientras carga el resaltado de sintaxis.

Los sitios de llamadas que Tim Schmelter enlazó en un comentario sobre la otra respuesta no están relacionados con el tiempo de ejecución que se está quedando sin memoria y no puede construir un objeto.

Aleatorio832
fuente