c# - usa - foreach en programacion
¿Cómo puede un recolector de basura evitar un ciclo infinito aquí? (3)
Considere el siguiente programa C #, lo presenté en codegolf como respuesta para crear un bucle sin bucle:
class P{
static int x=0;
~P(){
System.Console.WriteLine(++x);
new P();
}
static void Main(){
new P();
}
}
Este programa se ve como un ciclo infinito en mi inspección, pero parece ejecutarse durante varios miles de iteraciones, y luego el programa termina exitosamente sin error (no se generan errores). ¿Es una violación de especificaciones que el finalizador de P
finalmente no se llame?
Claramente, este es un código estúpido, que nunca debería aparecer, pero tengo curiosidad por saber cómo se podría completar el programa.
Código original de la publicación de golf :: https://codegolf.stackexchange.com/questions/33196/loop-without-looping/33218#33218
El finalizador no se ejecuta en el hilo principal. El finalizador tiene su propio hilo que ejecuta código, y no es un hilo de primer plano que mantendría la aplicación ejecutándose. El hilo principal se completa de manera efectiva de inmediato, momento en el cual el hilo del finalizador simplemente se ejecuta tantas veces como sea posible antes de que el proceso sea derribado. Nada mantiene vivo el programa.
Según Richter en la segunda edición de CLR a través de C # (sí, necesito actualizar):
Página 478
Para (el CLR se está cerrando) cada método Finalize tiene aproximadamente dos segundos para regresar. Si un método Finalize no regresa en dos segundos, el CLR simplemente mata el proceso; ya no se llaman a los métodos Finalize . Además, si lleva más de 40 segundos llamar a los métodos de finalización de todos los objetos, una vez más, el CLR simplemente elimina el proceso.
Además, como menciona Servy, tiene su propio hilo.
Un recolector de basura no es un sistema activo. Se ejecuta "a veces" y principalmente a pedido (por ejemplo, cuando todas las páginas que ofrece el sistema operativo están llenas).
La mayoría de los recolectores de basura se ejecutan de forma análoga a una generación en un subhebra. En la mayoría de los casos, puede pasar horas antes de que el objeto se recicle.
El único problema ocurre cuando quieres terminar el programa. Sin embargo, eso no es realmente un problema. Cuando use kill
un sistema operativo pedirá cortésmente que finalice los procesos. Sin embargo, cuando el proceso permanece activo, se puede usar kill -9
donde el sistema operativo elimina todo el control.
Cuando ejecuté su código en el entorno csharp
interactivo, obtuve:
csharp>
1
2
Unhandled Exception:
System.NotSupportedException: Stream does not support writing
at System.IO.FileStream.Write (System.Byte[] array, Int32 offset, Int32 count) [0x00000] in <filename unknown>:0
at System.IO.StreamWriter.FlushBytes () [0x00000] in <filename unknown>:0
at System.IO.StreamWriter.FlushCore () [0x00000] in <filename unknown>:0
at System.IO.StreamWriter.Write (System.Char[] buffer, Int32 index, Int32 count) [0x00000] in <filename unknown>:0
at System.IO.CStreamWriter.Write (System.Char[] buffer, Int32 index, Int32 count) [0x00000] in <filename unknown>:0
at System.IO.CStreamWriter.Write (System.Char[] val) [0x00000] in <filename unknown>:0
at System.IO.CStreamWriter.Write (System.String val) [0x00000] in <filename unknown>:0
at System.IO.TextWriter.Write (Int32 value) [0x00000] in <filename unknown>:0
at System.IO.TextWriter.WriteLine (Int32 value) [0x00000] in <filename unknown>:0
at System.IO.SynchronizedWriter.WriteLine (Int32 value) [0x00000] in <filename unknown>:0
at System.Console.WriteLine (Int32 value) [0x00000] in <filename unknown>:0
at P.Finalize () [0x00000] in <filename unknown>:0
Por lo tanto, su programa se bloquea porque stdout
está bloqueado por la terminación del entorno.
Al eliminar Console.WriteLine
y matar el programa. Después de cinco segundos, el programa finaliza (en otras palabras, el recolector de basura se da por vencido y simplemente liberará toda la memoria sin tener en cuenta los finalizadores).