visual terraria studio outofmemoryexception c# .net clr out-of-memory

terraria - system.outofmemoryexception c# solution



¿Cómo funciona la captura de una excepción OutOfMemoryException? (5)

Estoy un poco confundido sobre el hecho de que solo podemos detectar una OutOfMemoryException utilizando un bloque try / catch.

Dado el siguiente código:

Console.WriteLine("Starting"); for (int i = 0; i < 10; i++) { try { OutOfMemory(); } catch (Exception exception) { Console.WriteLine(exception.ToString()); } } try { StackOverflow(); } catch (Exception exception) { Console.WriteLine(exception.ToString()); } Console.WriteLine("Done");

Los métodos que utilicé para crear la excepción OutOfMemory + StackOverflowException:

public static void OutOfMemory() { List<byte[]> data = new List<byte[]>(1500); while (true) { byte[] buffer = new byte[int.MaxValue / 2]; for (int i = 0; i < buffer.Length; i++) { buffer[i] = 255; } data.Add(buffer); } } static void StackOverflow() { StackOverflow(); }

Imprime la OutOfMemoryException 10 veces y luego termina debido a la StackOverflowException , que no puede manejar.

El gráfico de RAM se ve así mientras se ejecuta el programa:

Mi pregunta ahora es ¿por qué podemos capturar la OutOfMemoryException ? Después de atraparlo, podemos seguir ejecutando el código que queramos. Según lo probado por el gráfico RAM, hay memoria liberada. ¿Cómo sabe el motor en tiempo de ejecución qué objetos puede GC y cuáles son necesarios para una ejecución posterior?


El GC realiza un análisis de las referencias que se utilizan en el programa y puede desechar cualquier objeto que no se use en ningún lugar.

Una OutOfMemoryException no significa que la memoria esté completamente agotada, solo significa que una asignación de memoria ha fallado. Si intentó asignar un área de memoria grande a la vez, es posible que aún quede suficiente memoria libre.

Cuando no hay suficiente memoria libre para una asignación, el sistema realiza una recolección de basura para intentar liberar memoria. Si todavía no hay suficiente memoria para la asignación, se lanzará la excepción.

No se puede manejar una Exception , porque significa que la pila está llena, y no es posible eliminar nada de ella como está con el montón. Necesitaría más espacio en la pila para continuar ejecutando el código que manejaría la excepción, pero no hay más.


Es posible que la excepción OutOfMemoryException se esté ejecutando porque está ejecutando un programa de 32 bits, con el gráfico de memoria que no ha indicado la cantidad de RAM que tiene el sistema, por lo que tal vez intente MemoryFailPoint como un bit de 64 bits y tal vez use MemoryFailPoint para evitar que esto ocurra.

También puede informarnos qué hay en la función OutOfMemory () para obtener una imagen más clara.

PS es el único error que no se puede manejar.

Edición: como se mencionó anteriormente, y pensé que era lógico y, por lo tanto, no lo mencioné antes, si por ejemplo trata de asignar más memoria de la que tiene ''disponible'', no es posible hacerlo y se produce una excepción. A medida que va asignando matrices grandes con sus datos, agregue () antes de que se produzca el agregado final "ilegal", por lo tanto, aún queda memoria libre.

Así que supongo que es en este punto data.Add (buffer); el problema se produce durante la creación de la matriz cuando se dispara el límite del proceso de 2 GB agregando una matriz de 400 MB de bytes a "datos", por ejemplo, una matriz de alrededor de 1 billón de objetos a 4 bytes por pieza que esperaría que ronden los 400 MB.

PS Hasta. La asignación de memoria de proceso máxima de 4.5 4.5 es de 2 GB, después de 4.5 están disponibles.


La razón por la que puede obtener una excepción OutOfMemoryException es porque el diseñador de idiomas decidió dejarlo. La razón por la que esto es a veces (pero no generalmente) práctico es porque es una situación recuperable en algunos casos.

Si intenta asignar una matriz enorme, puede obtener una excepción OutOfMemoryException, pero la memoria para esa matriz enorme no se habrá asignado realmente, por lo que otro código aún podrá ejecutarse sin problemas. Además, el desenrollamiento de la pila debido a la excepción puede hacer que otros objetos sean elegibles para la recolección de basura, lo que aumenta la cantidad de memoria disponible.


No estoy seguro de si esto responde a tu pregunta, pero esta es una explicación (simplificada) de cómo decide qué objetos limpiar:

El recolector de basura toma todos los subprocesos en ejecución en su programa y marca todos los objetos de nivel superior, lo que significa todos los objetos accesibles desde los marcos de la pila (es decir, todos los objetos apuntados por variables locales en los puntos donde se encuentra actualmente la ejecución), así como todos Objetos apuntados por campos estáticos.

Luego, marca los objetos del siguiente nivel, lo que significa todos los objetos señalados por todos los campos de los objetos marcados anteriormente. Este paso se repite hasta que no se marquen nuevos objetos.

Debido a que C # no permite punteros en el contexto normal, una vez que se completa el paso anterior, se garantiza que los objetos no marcados no sean accesibles por el código posterior y, por lo tanto, se pueden limpiar de forma segura.

En su caso, si los objetos que ha asignado para agregar presión al administrador de memoria no se mantienen por referencia, significa que el GC tendrá la oportunidad de limpiarlos. Además, tenga en cuenta que OutOfMemoryException se refiere a la memoria administrada de su programa CLR, mientras que el GC funciona un poco fuera de esa "caja".


Su método OutOfMemory() crea una estructura de datos (la List<byte[]> ) que es local al alcance del método. Mientras que su hilo de ejecución está dentro del método OutOfMemory , el marco de pila actual se considera la raíz de GC para la Lista. Una vez que su hilo termina en el bloque de captura, el marco de la pila se abrió y la lista se convirtió en inalcanzable. Por lo tanto, el recolector de basura determina que puede recopilar la lista de forma segura (lo que hace como lo ha observado en su gráfico de memoria).