Dado que todo tiene un límite, me preguntaba si hay un límite para la cantidad de for
bucles anidados o, mientras tenga memoria, puedo agregarlos, ¿puede el compilador de Visual Studio crear un programa de este tipo?
Por supuesto, 64 o más for
bucles anidados no serían útiles para depurar, pero ¿es factible?
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
fuente
fuente
Respuestas:
Me arriesgaré publicando esto, pero creo que la respuesta es:
Entre 550 y 575
con la configuración predeterminada en Visual Studio 2015
Creé un pequeño programa que genera
for
bucles anidados ...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); } } ... ... } }
Para 500 bucles anidados, el programa aún se puede compilar. Con 575 bucles, el compilador rescata:
con el mensaje del compilador subyacente
Por supuesto, este es un resultado puramente hipotético . Si el bucle más interno hace más de a
Console.WriteLine
, es posible que haya menos bucles anidados antes de que se exceda el tamaño de la pila. Además, esto puede no ser un límite estrictamente técnico, en el sentido de que puede haber configuraciones ocultas para aumentar el tamaño máximo de pila para el "Analizador" que se menciona en el mensaje de error, o (si es necesario) para el ejecutable resultante. Esta parte de la respuesta, sin embargo, se deja a las personas que conocen C # en profundidad.Actualizar
En respuesta a la pregunta en los comentarios :
Para ambos casos, la respuesta es: Sí, es posible. Al completar el método con 575 declaraciones generadas automáticamente
int i0=0; Console.WriteLine(i0); int i1=0; Console.WriteLine(i1); ... int i574=0; Console.WriteLine(i574);
todavía se puede compilar. Todo lo demás me hubiera sorprendido. El tamaño de pila que se requiere para las
int
variables es de solo 2,3 KB. Pero tenía curiosidad y, para probar otros límites, aumenté este número. Finalmente, no se compiló, lo que provocó el errorque es un punto interesante, pero ya se ha observado en otra parte: Número máximo de variables en el método
Del mismo modo, 575 bucles no anidados
for
, como enfor (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); }
también se puede compilar. Aquí, también intenté encontrar el límite y creé más de estos bucles. En particular, no estaba seguro de si las variables de bucle en este caso también cuentan como "locales", porque están en las suyas
{ block }
. Pero aún así, más de 65534 no es posible. Finalmente, agregué una prueba que consta de 40000 bucles del patrónfor (int i39999 = 0; i39999 < 10; i39999++) { int j = 0; Console.WriteLine(j + i39999); }
que contenía una variable adicional en el bucle, pero estos parecen contar también como "locales" y no fue posible compilar esto.
Entonces, para resumir: el límite de ~ 550 es causado por la profundidad de anidación de los bucles. Esto también fue indicado por el mensaje de error
La documentación del error CS1647 desafortunadamente (pero comprensiblemente) no especifica una "medida" de complejidad, sino que solo brinda consejos pragmáticos.
Para enfatizar esto nuevamente: para el caso particular de
for
bucles profundamente anidados , todo esto es bastante académico e hipotético . Pero la búsqueda web del mensaje de error de CS1647 revela varios casos en los que este error apareció para un código que probablemente no era intencionalmente complejo, sino que se creó en escenarios realistas.fuente
for
bucles. Microsoft BASIC tenía un límite de anidamiento de 8.42
como respuesta.No hay un límite estricto en la especificación del lenguaje C # o CLR. Su código sería iterativo, en lugar de recursivo, lo que podría conducir a un desbordamiento de pila bastante rápido.
Hay algunas cosas que podrían contar como un umbral, por ejemplo, el
int
contador (generalmente) que usaría, que asignaría una entradaint
en la memoria para cada bucle (y antes de haber asignado toda su pila con ints ...). Tenga en cuenta queint
se requiere el uso de eso y puede reutilizar la misma variable.Como señaló Marco , el umbral actual está más en el compilador que en la especificación del lenguaje real o en tiempo de ejecución. Una vez que se recodifica, es posible que tenga algunas iteraciones más. Si, por ejemplo, usa Ideone , que de forma predeterminada usa el compilador antiguo, puede obtener más de 1200
for
bucles fácilmente.Sin embargo, tanto for loops es un indicador de mal diseño. Espero que esta pregunta sea puramente hipotética.
fuente
int
). Si fueran bucles sin variable de bucle, entonces sería diferente.Hay un límite para todo C # compilado hasta MSIL. MSIL solo puede admitir 65535 variables locales. Si sus
for
bucles son como los que mostró en el ejemplo, cada uno requiere una variable.Es posible que su compilador pueda asignar objetos en el montón para que actúen como almacenamiento de variables locales, evitando este límite. Sin embargo, no estoy seguro de qué tipo de resultados extraños vendrían de eso. Puede haber problemas que surjan con la reflexión que hagan que este enfoque sea ilegal.
fuente
while(true)
lo que formaría un bucle infinito. Si editamos la pregunta a "¿Existe un límite para el número de bucles for anidados en un programa de terminación?" Entonces, ¿podríamos usar el truco de la variable local para formar un límite estricto?break
o hacer que la condición del bucle verifique algo externo, como( ; DateTime.now() < ... ; )
Entre 800 y 900 para
for(;;)
bucles vacíos .Enfoque reflejado de Marco13, excepto
for(;;)
bucles probados :for (;;) // 0 for (;;) // 1 for (;;) // 2 // ... for (;;) // n_max { // empty body }
Funcionó para 800 anidados
for(;;)
, pero dio el mismo error que Marco13 encontró al intentar 900 bucles.Cuando se compila,
for(;;)
parece bloquear el hilo sin maximizar la CPU; superficialmente, parece actuar como unThread.Sleep()
.fuente
for(;;)
sería un bucle infinito en C # ?! (No puedo probarlo ahora, pero si resulta ser incorrecto, eliminaré este comentario)for(;;)
se bloquea sin consumir tiempo de CPU.for(;;)
bucles están anidados, por lo que todos comienzan hasta el bucle más anidado, que es infinito. Para el primerofor(;;)
en bloquear, tendría que serlofor(;;){}
. En cuanto a por qué hacer esto, fue solo una prueba para ver qué limitaciones tiene la implementación actual de .NET / C #; aparentemente no puede llegar a los 900for(;;)
, aunque, como puede notar, no hace nada.