101 votes

Comment un éboueur n’évite une boucle infinie ici ?

Considérez les points suivants programme C#, je l'ai soumis sur codegolf comme une réponse de créer une boucle sans boucle:

class P{
    static int x=0;
    ~P(){
        System.Console.WriteLine(++x);
        new P();
    }
    static void Main(){
        new P();
    }
}

Ce programme ressemble à une boucle infinie dans mon inspection, mais il semble fonctionner pour plusieurs milliers d'itérations, puis le programme se termine sans erreur (Aucune erreur n'est renvoyée). C'est un spec violation que le finaliseur pour P finalement n'est pas appelé?

Clairement, c'est stupide de code, qui ne doit jamais apparaître, mais je suis curieux de savoir comment le programme pourrait jamais complète.

Le code d'origine de golf post:: http://codegolf.stackexchange.com/questions/33196/loop-without-looping/33218#33218

110voto

Eric Scherrer Points 2247

Comme par Richter, dans la seconde édition de la CLR via C# (oui j'ai besoin de mettre à jour):

Page 478

(Le CLR est en cours d'arrêt) chaque Finaliser la méthode est donnée environ deux secondes pour revenir. Si un de Finaliser la méthode ne retourne pas dans un délai de deux secondes, le CLR tue tout simplement le processus - plus de Finaliser les méthodes sont appelées. Aussi, si cela prend plus de 40 secondes pour appeler tous les objets de Finaliser les méthodes, encore une fois, le CLR tue tout simplement le processus.

Aussi, comme Servy mentionne, il a son propre thread.

23voto

Servy Points 93720

Le finaliseur ne fonctionne pas dans le thread principal. Le finaliseur a son propre thread qui exécute du code, et il n’est pas un thread de premier plan qui permettrait de maintenir l’application en cours d’exécution. Le thread principal complète efficacement tout de suite, à quel point le thread finaliseur s’exécute simplement autant de fois qu’il obtient une chance d’avant que le processus est démoli. Rien est perpétuer le programme.

8voto

CommuSoft Points 6439

Un garbage collector n'est pas un système actif. Il s'exécute "parfois" et surtout à la demande (par exemple lorsque toutes les pages offertes par l'OS sont pleins).

La plupart des éboueurs exécuter dans une largeur de première génération, à la manière d'un subthread. Dans la plupart des cas, il peut prendre des heures avant que l'objet est recyclé.

Le seul problème se produit lorsque vous souhaitez mettre fin au programme. Cependant ce n'est pas vraiment un problème. Lorsque vous utilisez kill un OS demander poliment de mettre fin à des processus. Lorsque le processus reste cependant actif, on peut utiliser kill -9 où le Système d'Exploitation supprime tout contrôle.

Quand j'ai couru votre code dans interactive csharp de l'environnement, j'ai:

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

Ainsi, votre programme se bloque parce qu' stdout est bloqué par le termintation de l'environnement.

Lors de la suppression de l' Console.WriteLine et de tuer le programme. Après cinq secondes, le programme se termine (en d'autres termes, le garbage collector donne simplement la volonté libre de toute mémoire, sans prendre les finaliseurs en compte).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X