Y a-t-il une limite au nombre de boucles ‘pour’ nestedes?

Comme tout a une limite, je me demandais s’il y avait une limite au nombre de boucles nestedes ou tant que j’avais de la mémoire, je peux les append, le compilateur Visual Studio peut-il créer un tel programme?

Bien sûr, un 64 ou plus nested for boucles ne serait pas pratique pour déboguer, mais est-ce faisable?

 private void TestForLoop() { for (int a = 0; a < 4; a++) { for (int b = 0; b < 56; b++) { for (int c = 0; c < 196; c++) { //etc.... } } } } 

    Je suis en train de sortir en postant ceci, mais je pense que la réponse est:

    Entre 550 et 575

    avec les parameters par défaut dans Visual Studio 2015

    J’ai créé un petit programme qui génère des boucles nestedes for

     for (int i0=0; i0<10; i0++) { for (int i1=0; i1<10; i1++) { ... ... for (int i573=0; i573<10; i573++) { for (int i574=0; i574<10; i574++) { Console.WriteLine(i574); } } ... ... } } 

    Pour 500 boucles nestedes, le programme peut toujours être compilé. Avec 575 boucles, le compilateur sort:

    Avertissement AD0001 Analyzer 'Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames.CSharpSimplifyTypeNamesDiagnosticAnalyzer' a généré une exception de type 'System.InsufficientExecutionStackException' avec le message 'Pile insuffisante pour continuer à exécuter le programme en toute sécurité. Cela peut être dû à un trop grand nombre de fonctions sur la stack d'appels ou à une fonction de la stack utilisant trop d'espace de stack.

    avec le message du compilateur sous-jacent

    erreur CS8078: une expression est trop longue ou complexe à comstackr

    Bien sûr, il s’agit d’un résultat purement hypothétique . Si la boucle la plus interne fait plus qu'une Console.WriteLine , alors moins de boucles nestedes sont possibles avant que la taille de la stack ne soit dépassée. En outre, cela peut ne pas être une limite ssortingctement technique, en ce sens qu'il peut y avoir des parameters cachés pour augmenter la taille maximale de la stack pour "l'Analyser" mentionnée dans le message d'erreur, ou (si nécessaire) pour l'exécutable résultant. Cette partie de la réponse, cependant, est laissée aux personnes qui connaissent C # en profondeur.


    Mettre à jour

    En réponse à la question dans les commentaires :

    Je serais intéressé de voir cette réponse élargie pour "prouver" expérimentalement si vous pouvez mettre 575 variables locales sur la stack si elles ne sont pas utilisées dans les boucles for, et / ou si vous pouvez mettre 575 boucles For-Lo non nestedes une seule fonction

    Dans les deux cas, la réponse est: oui, c'est possible. Lorsque vous remplissez la méthode avec 575 instructions générées automatiquement

     int i0=0; Console.WriteLine(i0); int i1=0; Console.WriteLine(i1); ... int i574=0; Console.WriteLine(i574); 

    il peut encore être compilé. Tout le rest m'aurait surpris. La taille de la stack requirejse pour les variables int n'est que de 2,3 Ko. Mais j'étais curieux et pour tester d'autres limites, j'ai augmenté ce nombre. Finalement, il n'a pas été compilé, provoquant l'erreur

    erreur CS0204: seules 65 534 sections locales, y compris celles générées par le compilateur, sont autorisées

    ce qui est un point intéressant, mais a déjà été observé ailleurs: nombre maximum de variables dans la méthode

    De même, 575 non nesteds for -loops, comme dans

     for (int i0=0; i0<10; i0++) { Console.WriteLine(i0); } for (int i1=0; i1<10; i1++) { Console.WriteLine(i1); } ... for (int i574=0; i574<10; i574++) { Console.WriteLine(i574); } 

    peut également être compilé. Ici, j'ai également essayé de trouver la limite et créé plus de ces boucles. En particulier, je ne savais pas si les variables de boucle dans ce cas sont aussi des "locales", car elles sont dans leur propre { block } . Mais encore, plus de 65534 n'est pas possible. Enfin, j'ai ajouté un test composé de 40000 boucles du pattern

     for (int i39999 = 0; i39999 < 10; i39999++) { int j = 0; Console.WriteLine(j + i39999); } 

    cela contenait une variable supplémentaire dans la boucle, mais celles-ci semblent également compter comme "locales", et il n'était pas possible de les comstackr.


    Donc pour résumer: la limite de ~ 550 est en effet causée par la profondeur d’imbrication des boucles. Cela a également été indiqué par le message d'erreur

    erreur CS8078: une expression est trop longue ou complexe à comstackr

    La documentation de l'erreur CS1647 malheureusement (mais compréhensible) ne spécifie pas une "mesure" de la complexité, mais donne seulement des conseils pragmatiques

    Il y a eu un dépassement de stack dans le compilateur traitant votre code. Pour résoudre cette erreur, simplifiez votre code.

    Encore une fois: pour le cas particulier des nesteds for boucles, tout cela est plutôt académique et hypothétique . Cependant, la recherche Web pour le message d'erreur de CS1647 révèle plusieurs cas où cette erreur est apparue pour le code qui n'était probablement pas intentionnellement complexe, mais créé dans des scénarios réalistes.

    Il n’y a pas de limite ssortingcte dans la spécification du langage C # ou dans le CLR. Votre code serait itératif, plutôt que récursif, ce qui pourrait entraîner un débordement de stack assez rapide.

    Il y a quelques choses qui pourraient compter comme seuil, par exemple le compteur (généralement) int vous utiliseriez, qui allouerait un int en mémoire pour chaque boucle (et avant que vous ayez alloué l’intégralité de votre stack avec ints …). Notez que l’utilisation de ce int est requirejse et vous pouvez réutiliser la même variable.

    Comme l’a souligné Marco , le seuil actuel est plus dans le compilateur que dans la spécification de langage ou l’exécution. Une fois que cela est recodé, vous pourriez avoir encore plus d’itérations. Si vous utilisez par exemple Ideone , qui utilise par défaut l’ancien compilateur, vous pouvez facilement obtenir plus de 1200 boucles for boucles.

    Cela pour les boucles est un indicateur de mauvaise conception cependant. J’espère que cette question est purement hypothétique.

    Il y a une limite pour tous les C # compilés à MSIL. MSIL ne peut prendre en charge que 65535 variables locales. Si vos boucles for sont comme celles que vous avez montrées dans l’exemple, chacune nécessite une variable.

    Il est possible que votre compilateur alloue des objects sur le tas pour agir comme stockage pour les variables locales, en contournant cette limite. Cependant, je ne suis pas sûr de ce genre de résultats bizarres. Il peut y avoir des problèmes de reflection qui rendent une telle approche illégale.

    Entre 800 et 900 pour les boucles vides for(;;) .

    L’approche de Marco13 en miroir, sauf for(;;) boucles for(;;) :

     for (;;) // 0 for (;;) // 1 for (;;) // 2 // ... for (;;) // n_max { // empty body } 

    Cela a fonctionné pour 800 nesteds for(;;) , mais cela a donné la même erreur que Marco13 lors de l’essai de 900 boucles.

    Quand il comstack, le for(;;) semble bloquer le thread sans maximiser le CPU; superficiellement, il semble agir comme un Thread.Sleep() .