Da alles begrenzt ist, habe ich mich gefragt, ob die Anzahl der verschachtelten for
Schleifen begrenzt ist oder ob ich sie hinzufügen kann, solange ich Speicher habe. Kann der Visual Studio-Compiler ein solches Programm erstellen?
Natürlich for
wären 64 oder mehr verschachtelte Schleifen nicht praktisch zum Debuggen, aber ist es machbar?
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....
}
}
}
}
c#
for-loop
compilation
limit
Fred Smith
quelle
quelle
Antworten:
Ich gehe auf die Nerven, indem ich dies poste, aber ich denke, dass die Antwort lautet:
Zwischen 550 und 575
mit Standardeinstellungen in Visual Studio 2015
Ich habe ein kleines Programm erstellt, das verschachtelte
for
Schleifen generiert ...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); } } ... ... } }
Für 500 verschachtelte Schleifen kann das Programm weiterhin kompiliert werden. Mit 575 Schleifen rettet der Compiler:
mit der zugrunde liegenden Compiler-Nachricht
Dies ist natürlich ein rein hypothetisches Ergebnis. Wenn die innerste Schleife mehr als a
Console.WriteLine
ausführt, sind möglicherweise weniger verschachtelte Schleifen möglich, bevor die Stapelgröße überschritten wird. Dies ist möglicherweise auch keine rein technische Grenze, da möglicherweise versteckte Einstellungen vorhanden sind, um die maximale Stapelgröße für den in der Fehlermeldung genannten "Analyzer" oder (falls erforderlich) für die resultierende ausführbare Datei zu erhöhen. Dieser Teil der Antwort bleibt jedoch den Leuten überlassen, die C # genau kennen.Aktualisieren
Als Antwort auf die Frage in den Kommentaren :
In beiden Fällen lautet die Antwort: Ja, das ist möglich. Beim Füllen der Methode mit 575 automatisch generierten Anweisungen
int i0=0; Console.WriteLine(i0); int i1=0; Console.WriteLine(i1); ... int i574=0; Console.WriteLine(i574);
es kann noch kompiliert werden. Alles andere hätte mich überrascht. Die für die
int
Variablen erforderliche Stapelgröße beträgt nur 2,3 KB. Aber ich war neugierig und um weitere Grenzen zu testen, habe ich diese Zahl erhöht. Schließlich wurde es nicht kompiliert, was den Fehler verursachteDas ist ein interessanter Punkt, wurde aber bereits an anderer Stelle beobachtet: Maximale Anzahl von Variablen in der Methode
In ähnlicher Weise 575 nicht verschachtelte
for
Schleifen, wie infor (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); }
kann auch kompiliert werden. Hier habe ich auch versucht, das Limit zu finden, und mehr dieser Schleifen erstellt. Insbesondere war ich mir nicht sicher, ob die Schleifenvariablen in diesem Fall auch als "Einheimische" gelten, weil sie in ihren eigenen sind
{ block }
. Mehr als 65534 ist jedoch nicht möglich. Schließlich habe ich einen Test hinzugefügt, der aus 40000 Schleifen des Musters bestehtfor (int i39999 = 0; i39999 < 10; i39999++) { int j = 0; Console.WriteLine(j + i39999); }
das enthielt eine zusätzliche Variable in der Schleife, aber diese scheinen auch als "Einheimische" zu zählen, und es war nicht möglich, diese zu kompilieren.
Zusammenfassend: Die Grenze von ~ 550 wird tatsächlich durch die Verschachtelungstiefe der Schleifen verursacht. Dies wurde auch durch die Fehlermeldung angezeigt
Die Dokumentation des Fehlers CS1647 spezifiziert leider (aber verständlicherweise) keine "Messung" der Komplexität, sondern gibt nur den pragmatischen Rat
Um dies noch einmal zu betonen: Für den speziellen Fall tief verschachtelter
for
Schleifen ist dies alles eher akademisch und hypothetisch . Die Websuche nach der Fehlermeldung von CS1647 zeigt jedoch mehrere Fälle, in denen dieser Fehler für Code auftrat, der höchstwahrscheinlich nicht absichtlich komplex war, sondern in realistischen Szenarien erstellt wurde.quelle
for
Schleifen hat. Microsoft BASIC hatte ein Verschachtelungslimit von 8.42
als Antwort gedacht .In der C # -Sprachenspezifikation oder der CLR gibt es keine feste Grenze. Ihr Code wäre eher iterativ als rekursiv, was sehr schnell zu einem Stapelüberlauf führen könnte.
Es gibt einige Dinge, die als Schwellenwert gelten könnten, z. B. den (allgemein) verwendeten
int
Zähler, derint
jeder Schleife einen In-Speicher zuweist (und bevor Sie Ihren gesamten Stapel mit Ints zugewiesen haben ...). Beachten Sie, dass die Verwendungint
erforderlich ist und Sie dieselbe Variable möglicherweise wiederverwenden.Wie von Marco hervorgehoben , liegt der aktuelle Schwellenwert mehr im Compiler als in der tatsächlichen Sprachspezifikation oder Laufzeit. Sobald dies neu codiert ist, können Sie weitere Iterationen durchführen. Wenn Sie beispielsweise Ideone verwenden , das standardmäßig den alten Compiler verwendet, können Sie
for
problemlos über 1200 Schleifen erhalten.So viel zu Loops ist jedoch ein Indikator für schlechtes Design. Ich hoffe, diese Frage ist rein hypothetisch.
quelle
int
). Wenn sie Schleifen ohne Schleifenvariable wären, wäre das anders.Es gibt ein Limit für alle C #, die bis zu MSIL kompiliert wurden. MSIL kann nur 65535 lokale Variablen unterstützen. Wenn Ihre
for
Schleifen denen entsprechen, die Sie im Beispiel gezeigt haben, benötigt jede eine Variable.Es ist möglich, dass Ihr Compiler Objekte auf dem Heap als Speicher für lokale Variablen zuweist und diese Grenze umgeht. Ich bin mir jedoch nicht sicher, welche seltsamen Ergebnisse daraus resultieren würden. Bei der Reflexion können Probleme auftreten, die einen solchen Ansatz illegal machen.
quelle
while(true)
einer Endlosschleife. Wenn wir die Frage auf "Gibt es eine Begrenzung für die Anzahl der verschachtelten for-Schleifen in einem Abschlussprogramm?" Könnten wir dann den lokalen Variablentrick verwenden, um ein hartes Limit zu bilden?break
oder die Schleifenbedingung etwas Externes überprüfen lassen, wie( ; DateTime.now() < ... ; )
Zwischen 800 und 900 für leere
for(;;)
Schleifen.Der Ansatz von Marco13 wurde gespiegelt, mit Ausnahme der versuchten
for(;;)
Schleifen:for (;;) // 0 for (;;) // 1 for (;;) // 2 // ... for (;;) // n_max { // empty body }
Es funktionierte für 800 verschachtelte
for(;;)
, aber es gab den gleichen Fehler, den Marco13 beim Versuch von 900 Schleifen hatte.Wenn es kompiliert wird,
for(;;)
scheint der Thread zu blockieren, ohne die CPU zu maximieren. oberflächlich scheint es sich wie ein zu verhaltenThread.Sleep()
.quelle
for(;;)
wäre eine Endlosschleife in C #?! (Ich kann esfor(;;)
blockiert, ohne CPU-Zeit zu verbrauchen.for(;;)
Schleifen sind verschachtelt, daher beginnen sie alle mit der am meisten verschachtelten Schleife, die unendlich ist. Für den erstenfor(;;)
Block musste es seinfor(;;){}
. Warum dies getan wurde, war nur ein Test, um festzustellen, welche Einschränkungen die aktuelle .NET / C # -Implementierung aufweist. anscheinend kann es nicht bis 900 gehenfor(;;)
, obwohl es, wie Sie bemerken, nichts tut.