stringtranslate.com

Bucle infinito

En programación de computadoras , un bucle infinito (o bucle sin fin ) [1] [2] es una secuencia de instrucciones que, tal como están escritas, continuarán sin fin, a menos que ocurra una intervención externa, como apagar la energía mediante un interruptor o desconectar un enchufe. . Puede que sea intencionado.

Descripción general

Esto difiere de "un tipo de programa informático que ejecuta las mismas instrucciones continuamente hasta que se detiene o se interrumpe". [3] Considere el siguiente pseudocódigo :

how_many  =  0 while  is_there_more_data ()  do  how_many  =  how_many  +  1 end display  "el número de elementos contados = "  how_many

Las mismas instrucciones se ejecutaron continuamente hasta que se detuvieron o interrumpieron . . . por el FALSO devuelto en algún momento por la función is_there_more_data .

Por el contrario, el siguiente bucle no terminará por sí solo:

pájaros  =  1 pez  =  2 mientras  pájaros  +  pez  >  1  hacer  pájaros  =  3  -  pájaros  pez  =  3  -  pez final

las aves alternarán siendo 1 o 2, mientras que los peces alternarán siendo 2 o 1. El bucle no se detendrá a menos que ocurra una intervención externa ("desconectar").

Detalles

Un bucle infinito es una secuencia de instrucciones en un programa de computadora que se repite sin cesar, ya sea porque el bucle no tiene una condición de terminación, [4] tiene una que nunca se puede cumplir o porque hace que el bucle comience de nuevo. En sistemas operativos más antiguos con multitarea cooperativa , [5] los bucles infinitos normalmente provocaban que todo el sistema dejara de responder. Con el modelo multitarea preventivo que ahora prevalece, los bucles infinitos generalmente hacen que el programa consuma todo el tiempo disponible del procesador, pero generalmente un usuario puede finalizarlo. Los bucles de espera ocupados también se denominan a veces "bucles infinitos". Los bucles infinitos son una posible causa de que una computadora se cuelgue o se congele ; otros incluyen ataques , interbloqueos y violaciones de acceso .

Bucle intencionado o no intencionado

Hacer un bucle es repetir un conjunto de instrucciones hasta que se cumpla una condición específica. Un bucle infinito ocurre cuando la condición nunca se cumplirá debido a alguna característica inherente del bucle.

Bucle intencional

Hay algunas situaciones en las que este es el comportamiento deseado. Por ejemplo, los juegos de las consolas de juegos basadas en cartuchos normalmente no tienen ninguna condición de salida en su bucle principal, ya que no hay ningún sistema operativo al que pueda salir el programa; el bucle se ejecuta hasta que se apaga la consola.

Las computadoras interactivas modernas requieren que la computadora esté constantemente monitoreando las entradas del usuario o la actividad del dispositivo, por lo que en algún nivel fundamental hay un bucle inactivo de procesamiento infinito que debe continuar hasta que el dispositivo se apaga o se reinicia. En la Computadora de Orientación Apollo , por ejemplo, este bucle externo estaba contenido en el programa Exec, [6] y si la computadora no tenía absolutamente ningún otro trabajo que hacer, ejecutaba en bucle un trabajo ficticio que simplemente apagaba la "actividad de la computadora". " luz indicadora.

Las computadoras modernas tampoco suelen detener los relojes que controlan los circuitos del procesador o de la placa base cuando fallan. En lugar de eso, vuelven a caer en una condición de error que muestra mensajes al operador (como la pantalla azul de la muerte ) y entran en un bucle infinito esperando que el usuario responda a un mensaje para continuar o reinicie el dispositivo.

Bloqueos giratorios

Los spinlocks son mecanismos de sincronización de bajo nivel que se utilizan en la programación concurrente para proteger los recursos compartidos. A diferencia de los candados tradicionales que ponen un hilo a dormir cuando no puede adquirir el candado, los spinlocks "giran" repetidamente en un bucle infinito hasta que el candado esté disponible. Este bucle infinito intencional es una elección de diseño deliberada destinada a minimizar el tiempo que un subproceso pasa esperando el bloqueo y evitar la sobrecarga de mecanismos de sincronización de nivel superior, como los mutex .

subprocesos múltiples

En programas de subprocesos múltiples, algunos subprocesos se pueden ejecutar dentro de bucles infinitos sin que todo el programa quede atrapado en un bucle infinito. Si el hilo principal sale, todos los hilos del proceso se detienen a la fuerza, por lo que toda ejecución finaliza y el proceso/programa finaliza. Los subprocesos dentro de los bucles infinitos pueden realizar tareas de "limpieza" o pueden estar en un estado bloqueado esperando entrada (desde socket/cola) y reanudar la ejecución cada vez que se recibe entrada.

Bucle involuntario

Una pantalla azul de la muerte en Windows XP . "El controlador del dispositivo se quedó atascado en un bucle infinito".

Muy a menudo, el término se utiliza para aquellas situaciones en las que este no es el resultado deseado; es decir, cuando se trata de un error . [7] Estos errores son más comunes entre los programadores novatos, pero también los pueden cometer programadores experimentados, porque sus causas pueden ser bastante sutiles.

Una causa común, por ejemplo, es que un programador intenta iterar sobre una secuencia de nodos en una estructura de datos como una lista enlazada o un árbol , ejecutando el código de bucle una vez para cada nodo. Los vínculos mal formados pueden crear un bucle de referencia en la estructura de datos, donde un nodo se vincula con otro que ocurre anteriormente en la secuencia. Esto convierte parte de la estructura de datos en un anillo , lo que hace que el código ingenuo se repita para siempre.

Si bien la mayoría de los bucles infinitos se pueden encontrar mediante una inspección minuciosa del código, no existe un método general para determinar si un programa determinado se detendrá alguna vez o se ejecutará para siempre; ésta es la indecidibilidad del problema de la detención . [8]

Interrupción

Mientras el sistema responda, los bucles infinitos a menudo pueden interrumpirse enviando una señal al proceso (como SIGINT en Unix) o una interrupción al procesador, lo que provoca que se aborte el proceso actual. Esto se puede hacer en un administrador de tareas , en una terminal con el comando Control-C , [9] o usando el comando kill o la llamada al sistema . Sin embargo, esto no siempre funciona, ya que es posible que el proceso no responda a las señales o que el procesador se encuentre en un estado ininterrumpible, como en el error de coma de Cyrix (causado por la superposición de instrucciones ininterrumpibles en una canalización de instrucciones ). En algunos casos, otras señales como SIGKILL pueden funcionar, ya que no requieren que el proceso responda, mientras que en otros casos el bucle no se puede terminar antes de que se apague el sistema.

Ayuda de idioma

Se pueden implementar bucles infinitos utilizando varias construcciones de flujo de control . Lo más común es que en la programación no estructurada se trate de un salto hacia atrás ( goto ), mientras que en la programación estructurada se trata de un bucle indefinido ( while loop ) configurado para no terminar nunca, ya sea omitiendo la condición o estableciéndola explícitamente en verdadero, como while (true) ....

Algunos lenguajes tienen construcciones especiales para bucles infinitos, normalmente omitiendo la condición de un bucle indefinido. Los ejemplos incluyen Ada ( loop ... end loop), [10] Fortran ( DO ... END DO), Go ( for { ... }), Ruby ( loop do ... end) y Rust ( loop { ... }).

Ejemplos de bucles infinitos intencionales

Un ejemplo simple (en C ):

#incluir <stdio.h> int main () { for (;;) // o equivalente, while (1) printf ( "Bucle infinito \n " ); devolver 0 ; }        

La forma for (;;)de un bucle infinito es tradicional, aparece en la referencia estándar El lenguaje de programación C y, a menudo, se pronuncia en forma de juego de palabras "para siempre". [11]

Este es un bucle que imprimirá "Infinite Loop" sin detenerse.

Un ejemplo similar en BASIC de la década de 1980 :

10 IMPRIMIR "BUCLE INFINITO" 20 IR A 10    

Un ejemplo similar en archivos por lotes de DOS :

: Un eco Bucle Infinito ir a  : A

Aquí el bucle es bastante obvio, ya que la última línea devuelve incondicionalmente la ejecución a la primera.

Un ejemplo en Java

mientras ( verdadero ) { Sistema . afuera . println ( "Bucle Infinito" ); }   

Un ejemplo en Bourne Again Shell

para (( ;; )) ; hacer eco del "Bucle Infinito" hecho   

Un ejemplo en Rust

bucle { imprimir! ( "Bucle infinito" ); }  

Ejemplos de bucles infinitos no intencionados

Errores matemáticos

A continuación se muestra un ejemplo de un bucle infinito en Visual Basic :

dim x como entero hacer while x < 5 x = 1 x = x + 1 bucle               

Esto crea una situación en la que xnunca será mayor que 5, ya que al inicio del código del bucle, xse le asigna el valor de 1 (independientemente de cualquier valor anterior) antes de que se cambie a x+ 1. Por lo tanto, el bucle siempre resultará en x= 2 y nunca se romperá. Esto podría solucionarse moviendo la x = 1instrucción fuera del bucle para que su valor inicial se establezca solo una vez.

En algunos lenguajes, la confusión del programador sobre los símbolos matemáticos puede provocar un bucle infinito involuntario. Por ejemplo, aquí hay un fragmento en C :

#incluir <stdio.h> int principal ( vacío ) { int a = 0 ; mientras ( a < 10 ) { printf ( "%d \n " , a ); if ( a = 5 ) printf ( "a es igual a 5! \n " ); un ++ ; } devolver 0 ; }                     

El resultado esperado son los números del 0 al 9, con un "¡a es igual a 5!" entre 5 y 6. Sin embargo, en la línea " if (a = 5)" anterior, el operador = (asignación) se confundió con el operador == (prueba de igualdad). En cambio, esto asignará el valor de 5 a aeste punto del programa. Por lo tanto, anunca podrá avanzar a 10 y este ciclo no puede terminar.

Errores de redondeo

Un comportamiento inesperado al evaluar la condición de terminación también puede causar este problema. Aquí hay un ejemplo en C :

flotador x = 0,1 ; mientras ( x != 1.1 ) { printf ( "x = %22.20f \n " , x ); x += 0,1 ; }            

En algunos sistemas, este bucle se ejecutará diez veces como se esperaba, pero en otros sistemas nunca terminará. El problema es que la condición de terminación del bucle (x != 1.1)prueba la igualdad exacta de dos valores de punto flotante , y la forma en que se representan los valores de punto flotante en muchas computadoras hará que esta prueba falle, porque no pueden representar el valor 0,1 exactamente, introduciendo así errores de redondeo en cada uno. incremento (ver cuadro).

Lo mismo puede suceder en Python :

x  =  0,1 mientras  x  !=  1 :  imprimir ( x )  x  +=  0,1

Debido a la probabilidad de que las pruebas de igualdad o no igualdad fallen inesperadamente, es más seguro utilizar pruebas de mayor o menor que cuando se trabaja con valores de punto flotante. Por ejemplo, en lugar de probar si xes igual a 1,1, se podría probar si (x <= 1.0), o (x < 1.1), cualquiera de los cuales seguramente saldrá después de un número finito de iteraciones. Otra forma de solucionar este ejemplo en particular sería utilizar un número entero como índice de bucle , contando el número de iteraciones que se han realizado.

Un problema similar ocurre frecuentemente en el análisis numérico : para calcular un resultado determinado, se pretende realizar una iteración hasta que el error sea menor que una tolerancia elegida. Sin embargo, debido a errores de redondeo durante la iteración, nunca se puede alcanzar la tolerancia especificada, lo que da como resultado un bucle infinito.

Bucles multipartidistas

Un bucle infinito puede deberse a la interacción de varias entidades. Considere un servidor que siempre responde con un mensaje de error si no comprende la solicitud. Incluso si no hay posibilidad de un bucle infinito dentro del propio servidor, un sistema que comprende dos de ellos ( A y B ) puede bucle sin fin: si A recibe un mensaje de tipo desconocido de B , entonces A responde con un mensaje de error a B ; si B no comprende el mensaje de error, responde a A con su propio mensaje de error; si A no comprende el mensaje de error de B , envía otro mensaje de error más, y así sucesivamente.

Un ejemplo común de tal situación es un bucle de correo electrónico . Un ejemplo de bucle de correo electrónico es si alguien recibe un correo de una bandeja de entrada sin respuesta, pero su respuesta automática está activada. Responderán a la bandeja de entrada sin respuesta, lo que activará la respuesta "esta es una bandeja de entrada sin respuesta". Esto se enviará al usuario, quien luego enviará una respuesta automática a la bandeja de entrada de no respuesta, y así sucesivamente.

Bucles pseudoinfinitos

Un bucle pseudoinfinito es un bucle que parece infinito pero que en realidad es sólo un bucle muy largo.

números muy grandes

Un ejemplo en bash :

para  x en $( sec 1000000000 ) ; hacer #código de bucle hecho    

Condición de terminación imposible

Un ejemplo de bucle en C :

int sin firmar yo ; for ( i = 1 ; i ! = 0 ; i ++ ) { /* código de bucle */ }           

Parece que esto continuará indefinidamente, pero de hecho el valor de ieventualmente alcanzará el valor máximo almacenable en an unsigned inty al agregar 1 a ese número volverá a 0, rompiendo el ciclo. El límite real idepende de los detalles del sistema y del compilador utilizado. Con aritmética de precisión arbitraria , este bucle continuaría hasta que la memoria de la computadora ya no pudiera contenerlo i. Si ifuera un entero con signo, en lugar de un entero sin signo, el desbordamiento no estaría definido. En este caso, el compilador podría optimizar el código en un bucle infinito.

recursividad infinita

La recursividad infinita es un caso especial de bucle infinito causado por la recursividad .

El siguiente ejemplo en Visual Basic para Aplicaciones (VBA) devuelve un error de desbordamiento de pila :

Sub Prueba1 () Llamar a Prueba1 Fin Sub    

Declaración de ruptura

Un while (true)bucle " " parece infinito a primera vista, pero puede haber una forma de escapar del bucle mediante una declaración break o una declaración return . Ejemplo en PHP :

mientras  ( verdadero )  {  si  ( $foo -> barra ())  {  retorno ;  } }

Bucle de Alderson

Bucle de Alderson es un término poco común de jerga o jerga para un bucle infinito donde hay una condición de salida disponible, pero inaccesible en una implementación del código, generalmente debido a un error del programador. Estos son los más comunes y visibles al depurar el código de la interfaz de usuario .

Un ejemplo de pseudocódigo similar a C de un bucle de Alderson, donde se supone que el programa suma números dados por el usuario hasta obtener cero, pero donde se usa el operador incorrecto:

suma entera = 0 ; int yo ; while ( true ) { printf ( "Ingrese un número para agregarlo a la suma o 0 para salir" ); i = getUserInput (); if ( i * 0 ) { // si i multiplicado por 0 es verdadero, suma i a la suma. Nota: CERO significa FALSO, distinto de cero significa VERDADERO. ¡"i * 0" es CERO (FALSO)! suma += yo ; // la suma nunca cambia porque (i * 0) es 0 para cualquier i; cambiaría si tuviéramos != en la condición en lugar de * } if ( sum > 100 ) { break ; // terminar el ciclo; La condición de salida existe pero nunca se alcanza porque la suma nunca se suma a } }                             

El término supuestamente recibió su nombre de un programador (apellido Alderson) que en 1996 [12] había codificado un cuadro de diálogo modal en Microsoft Access sin un botón Aceptar o Cancelar, deshabilitando así todo el programa cada vez que aparecía el cuadro. [13]

Ver también

Referencias

  1. ^ "Definición de diccionario de bucle sin fin". Archivado desde el original el 1 de agosto de 2020 . Consultado el 22 de enero de 2020 .
  2. ^ "¿Qué es el bucle infinito (bucle sin fin)?". Archivado desde el original el 15 de julio de 2019 . Consultado el 22 de enero de 2020 .
  3. ^ Caruso, Denise (16 de agosto de 1999). "La sobrecarga de colgados crea un viaje lleno de baches para las acciones de Internet". Los New York Times . Archivado desde el original el 27 de diciembre de 2019 . Consultado el 27 de diciembre de 2019 .
  4. ^ "Códigos y modos: el carácter de la cultura documental". Diario de flujo . Noviembre de 2014. Archivado desde el original el 1 de agosto de 2020 . Consultado el 23 de enero de 2020 . un bucle infinito es aquel que carece de... una condición de salida
  5. ^ también conocido como multitarea no preventiva: "Multitarea no preventiva". Revista PC . Archivado desde el original el 26 de julio de 2019 . Consultado el 7 de febrero de 2024 .
  6. ^ David Hoag (septiembre de 1976). "La historia de la orientación, navegación y control a bordo del Apolo" (PDF) . Laboratorio Charles Stark Draper. Archivado (PDF) desde el original el 5 de noviembre de 2016 . Consultado el 23 de enero de 2020 .
  7. ^ "Respuestas de crucigramas del New York Times". 13 de octubre de 2013. Archivado desde el original el 2 de agosto de 2020 . Consultado el 22 de enero de 2020 . informática... un defecto... que... hacer un bucle
  8. ^ "Problema de detención en teoría de la computación". 3 de octubre de 2018. Archivado desde el original el 9 de agosto de 2020 . Consultado el 22 de enero de 2020 .
  9. ^ "Un exploit de desbordamiento de búfer contra el software de control remoto DameWare". 19 de diciembre de 2003. Archivado desde el original el 24 de julio de 2020 . Consultado el 22 de enero de 2020 . Tan pronto como se cierra el shell de comandos con una combinación control-c...
  10. ^ Programación Ada: Control: Bucle sin fin
  11. ^ "Bucle sin fin en C/C++". Archivado desde el original el 3 de agosto de 2016.
  12. ^ Lee Dohm (24 de mayo de 2013). "Bucle de Alderson". Archivado desde el original el 19 de junio de 2020 . Consultado el 22 de enero de 2020 .
  13. ^ "Bucle de Alderson". El archivo Jergon , versión 4.4.7 . Archivado desde el original el 15 de mayo de 2006 . Consultado el 21 de mayo de 2006 .

enlaces externos