Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

В компьютерном программировании , в бесконечном цикле (или бесконечный цикл ) [1] [2] представляет собой последовательность инструкций , которые, как написано, будет продолжаться до бесконечности, если не происходит внешнее вмешательство ( «вилку»). Это может быть намеренно.

Обзор [ править ]

Это отличается от:

  • «тип компьютерной программы, которая выполняет одни и те же инструкции непрерывно, пока она не будет остановлена ​​или прервана». [3]

Учитывать:

how_many  =  0, а  is_there_more_data ()  do  how_many  =  how_many  +  1 end display  "количество подсчитанных элементов ="  how_many

Одни и те же инструкции выполнялись непрерывно, пока не были остановлены или прерваны . . . по ЛОЖЬ возвращенного в какой - то момент с помощью функции is_there_more_data .

Напротив, следующий цикл не закончится сам по себе:

птицы  =  1 рыба  =  2, а  птицы  +  рыба  >  1  делают  птицы  =  3  -  птицы  рыба  =  3  -  конец рыбы

птицы будут поочередно быть 1 или 2, а рыба - 2 или 1. Петля не остановится, если не произойдет внешнее вмешательство («вытащите пробку»).

Подробности [ править ]

Бесконечный цикл представляет собой последовательность инструкций в компьютерной программе , которая петля бесконечно, либо из - за петлю , не имеющей условия завершения, [4] , имеющие один , который никогда не может быть выполнен, или тот , который вызывает цикл , чтобы начать все сначала. В более старых операционных системах с кооперативной многозадачности , [5] бесконечные циклы обычно вызывается вся система перестанет отвечать на запросы. При распространенной в настоящее время модели вытесняющей многозадачности бесконечные циклы обычно заставляют программу использовать все доступное процессорное время, но обычно могут быть прерваны пользователем. Занято ждатьциклы также иногда называют «бесконечными циклами». Бесконечные циклы - одна из возможных причин " зависания " компьютера ; другие включают перебивание , взаимоблокировку и нарушения доступа .

Преднамеренное и непреднамеренное зацикливание [ править ]

Цикл - это повторение набора инструкций до тех пор, пока не будет выполнено определенное условие. Бесконечный цикл возникает, когда условие никогда не будет выполнено из-за некоторой внутренней характеристики цикла.

Преднамеренное зацикливание [ править ]

Есть несколько ситуаций, когда это желаемое поведение. Например, игры на игровых консолях на основе картриджей обычно не имеют условия выхода в их основном цикле, так как нет операционной системы, из которой программа могла бы выйти; цикл работает до тех пор, пока консоль не будет выключена.

Современные интерактивные компьютеры требуют, чтобы компьютер постоянно отслеживал ввод данных пользователем или активность устройства, поэтому на каком-то фундаментальном уровне существует бесконечный цикл ожидания обработки, который должен продолжаться до тех пор, пока устройство не будет выключено или перезагружено. В управляющем компьютере Apollo , например, этот внешний цикл содержался в программе Exec [6], и если бы у компьютера не было абсолютно никакой другой работы, он бы запустил фиктивное задание, которое просто отключило бы «активность компьютера» индикатор.

Современные компьютеры также обычно не останавливают тактовые частоты процессора или материнской платы, когда они выходят из строя. Вместо этого они возвращаются к состоянию ошибки, отображая сообщения для оператора, и входят в бесконечный цикл, ожидая, пока пользователь либо ответит на запрос о продолжении, либо сбросит устройство.

Многопоточность [ править ]

В многопоточных программах некоторые потоки могут выполняться внутри бесконечных циклов, не вызывая застревания всей программы в бесконечном цикле. Если основной поток завершает работу, все потоки процесса принудительно останавливаются, таким образом, все выполнение завершается, а процесс / программа завершается. Потоки внутри бесконечных циклов могут выполнять «служебные» задачи или они могут находиться в заблокированном состоянии, ожидая ввода (из сокета / очереди) и возобновлять выполнение каждый раз, когда вводится.

Непреднамеренное зацикливание [ править ]

Чаще всего термин используется для тех ситуаций, когда это не желаемый результат; то есть, когда это ошибка . [7] Такие ошибки чаще всего встречаются среди начинающих программистов, но могут быть сделаны и опытными программистами, потому что их причины могут быть довольно незаметными.

Одна из распространенных причин, например, состоит в том, что программист намеревается перебрать последовательность узлов в такой структуре данных , как связанный список или дерево , выполняя код цикла один раз для каждого узла. Неправильно сформированные связи могут создать ссылочный цикл в структуре данных, где один узел связывается с другим, возникающим раньше в последовательности. Это превращает часть структуры данных в кольцо , вызывая бесконечный цикл наивного кода.

Хотя большинство бесконечных циклов можно обнаружить путем тщательного изучения кода, не существует общего метода определения, остановится ли данная программа когда-либо или будет работать вечно; это неразрешимость от проблемы остановки . [8]

Прерывание [ править ]

Пока система реагирует, бесконечные циклы часто могут быть прерваны, посылая сигнал процессу (например, SIGINT в Unix) или прерывание процессору, вызывая прерывание текущего процесса. Это может быть сделано в диспетчере задач , в терминале с Control-C командой, [9] или с помощью убить команду или системный вызов . Однако это не всегда работает, так как процесс может не отвечать на сигналы или процессор может находиться в бесперебойном состоянии, например, при ошибке комы Cyrix (вызванной перекрытием непрерывных инструкций в конвейере команд.). В некоторых случаях могут работать другие сигналы, такие как SIGKILL , поскольку они не требуют, чтобы процесс реагировал, в то время как в других случаях цикл не может быть завершен без завершения работы системы.

Языковая поддержка [ править ]

Бесконечные циклы могут быть реализованы с использованием различных конструкций потока управления . Чаще всего в неструктурированном программировании это возврат назад ( goto ), тогда как в структурированном программировании это неопределенный цикл (цикл while), для которого задано никогда не заканчиваться, либо путем исключения условия, либо путем явной установки его в значение true, as while (true) ....

В некоторых языках есть специальные конструкции для бесконечных циклов, обычно путем исключения условия из неопределенного цикла. Примеры включают Ada ( loop ... end loop), [10] Fortran ( DO ... END DO), Go ( for { ... }) и Ruby ( loop do ... end).

Примеры намеренных бесконечных циклов [ править ]

Простой пример (на C ):

#include  <stdio.h>int  main (){ for  (;;)  // или эквивалентно while (1) { printf ( "Бесконечный цикл \ п " ); } возврат  0 ;}

Форма for (;;)бесконечного цикла традиционна, она встречается в стандартном справочнике по языку программирования C и часто произносится как «навсегда». [11]

Это цикл, который будет печатать «Бесконечный цикл» без остановки.

Похожий пример из BASIC 80-х :

10 ПЕЧАТЬ «БЕСКОНЕЧНОЙ ПЕТЛИ» 20 НАЙТИ 10    

Аналогичный пример в пакетных файлах DOS :

: A echo Infinite Loop goto  : A

Здесь цикл довольно очевиден, поскольку последняя строка безоговорочно отправляет выполнение обратно первой.

Пример на Java

while  ( true )  System . из . println ( «Бесконечный цикл» );

Пример в Bourne Again Shell

для  (( ;; )) ;  do echo  "Infinite Loop" готово

Пример в Rust

loop {  println ! ( «Бесконечный цикл» );}

Примеры непреднамеренных бесконечных циклов [ править ]

Математические ошибки [ править ]

Вот один пример бесконечного цикла в Visual Basic :

dim  x  as  integer do  while  x  <  5  x  =  1  x  =  x  +  1 цикл

Это создает ситуацию, когда xникогда не будет больше 5, поскольку в начале кода цикла xдается значение 1, таким образом, цикл всегда будет заканчиваться на 2, и цикл никогда не прервется. Это можно исправить, переместив x = 1инструкцию за пределы цикла. По сути, этот бесконечный цикл дает компьютеру команду продолжать прибавлять 1 к 1, пока не будет достигнуто 5. Поскольку 1 + 1 всегда равно 2, этого никогда не произойдет.

В некоторых языках путаница программиста с математическими символами может привести к непреднамеренному возникновению бесконечного цикла. Например, вот фрагмент кода на C :

#include  <stdio.h>Int  Основной ( недействительными ) {  INT  = 0 ; в то время как ( a < 10 ) { printf ( "% d \ n " , a ); if ( a = 5 ) printf ( "a равно 5! \ n " ); а ++ ; } return 0 ; }                  

Ожидаемый результат - числа от 0 до 9 с вставленным "a равно 5!" между 5 и 6. Однако в строке " if (a = 5)" выше программист перепутал оператор = (присваивание) с оператором == (проверка равенства). Вместо этого aна данном этапе программы будет присвоено значение 5 . Таким образом, aникогда не сможет перейти к 10, и этот цикл не может завершиться.

Ошибки округления [ править ]

Неожиданное поведение при оценке условия завершения также может вызвать эту проблему. Вот пример на C :

float  x  =  0,1 ; в то время как  ( x  ! =  1.1 )  {  printf ( "x =% 22.20f \ n " ,  x );  х  + =  0,1 ; }

В некоторых системах этот цикл будет выполняться десять раз, как ожидалось, но в других системах он никогда не завершится. Проблема в том, что условие завершения цикла (x! = 1.1) проверяет точное равенство двух значений с плавающей запятой , а способ представления значений с плавающей запятой на многих компьютерах приведет к сбою этого теста, потому что они не могут точно представить значение 0,1, таким образом вводя ошибки округления на каждом приращении (см. рамку).

То же самое может случиться и в Python :

x  =  0,1, а  x  ! =  1 :  print ( x )  x  + =  0,1

Из-за вероятности неожиданного сбоя тестов на равенство или неравенство, безопаснее использовать тесты больше или меньше при работе со значениями с плавающей запятой. Например, вместо проверки, xравно ли 1.1, можно проверить, будет ли (x <= 1.0) или (x <1.1) , любой из которых обязательно завершится после конечного числа итераций. Другой способ исправить этот конкретный пример - использовать целое число в качестве индекса цикла , подсчитывая количество выполненных итераций.

Подобная проблема часто возникает при численном анализе : для вычисления определенного результата предполагается выполнение итерации до тех пор, пока ошибка не станет меньше выбранного допуска. Однако из-за ошибок округления во время итерации указанный допуск никогда не может быть достигнут, что приводит к бесконечному циклу.

Многопартийные петли [ править ]

Бесконечный цикл может быть вызван взаимодействием нескольких сущностей. Рассмотрим сервер, который всегда отвечает сообщением об ошибке, если он не понимает запрос. Даже если нет возможности для бесконечного цикла внутри самого сервера, система, состоящая из двух из них ( A и B ), может зацикливаться бесконечно: если A получает сообщение неизвестного типа от B , то A отвечает сообщением об ошибке B ; если B не понимает сообщение об ошибке, он отвечает A своим сообщением об ошибке; если A не понимает сообщение об ошибке от B , он отправляет еще одно сообщение об ошибке и так далее.

Один из распространенных примеров такой ситуации - цикл электронной почты . Примером цикла электронной почты является случай, когда кто-то получает почту из почтового ящика без ответа, но его автоответчик включен. Они ответят на почтовый ящик без ответа, вызывая ответ «это почтовый ящик без ответа». Это будет отправлено пользователю, который затем отправит автоматический ответ в почтовый ящик без ответа и так далее и так далее.

Псевдобесконечные циклы [ править ]

Псевдобесконечный цикл - это цикл, который кажется бесконечным, но на самом деле это просто очень длинный цикл.

Очень большие числа [ править ]

Пример в bash :

для x в долларах ( seq 1000000000 ) ;  do #loop code done

Невозможное условие прекращения [ править ]

Пример цикла в C :

беззнаковый  int  i ; for  ( i  =  1 ;  i  ! =  0 ;  i ++ )  {  / * код цикла * / }

Похоже, что это будет продолжаться бесконечно, но на самом деле значение в iконечном итоге достигнет максимального значения, хранимого в a, unsigned intи добавление 1 к этому числу приведет к переходу к 0, разорвав цикл. Фактический предел iзависит от деталей используемой системы и компилятора . При арифметике произвольной точности этот цикл будет продолжаться до тех пор, пока память компьютера не перестанет удерживаться i. Если бы iбыло целое число со знаком, а не целое число без знака, переполнение было бы неопределенным. В этом случае компилятор может оптимизировать код до бесконечного цикла.

Бесконечная рекурсия [ править ]

Бесконечная рекурсия - это частный случай бесконечного цикла, вызванного рекурсией .

Следующий пример в VBA возвращает ошибку переполнения стека :

Sub  Test1 ()  Вызов  Test1 End  Sub

Оператор разрыва [ править ]

На while (true)первый взгляд цикл выглядит "" бесконечным, но может быть способ выйти из цикла с помощью оператора break или return . Пример на PHP :

в то время как  ( истина )  {  если  ( $ foo -> bar ())  {  возврат ;  } }

Петля Алдерсона [ править ]

Цикл Алдерсона - это редкий жаргонный или жаргонный термин для обозначения бесконечного цикла, в котором условие выхода доступно, но недоступно в текущей реализации кода, как правило, из-за ошибки программиста. Они наиболее распространены и видны при отладке кода пользовательского интерфейса .

Пример C-подобного псевдокода цикла Алдерсона, где программа должна суммировать числа, заданные пользователем, до тех пор, пока не будет дан ноль, но где программист использовал неправильный оператор:

int  sum  =  0 ; int  i ; while  ( true )  {  printf ( "Введите число, чтобы добавить к сумме, или 0, чтобы выйти" );  я  =  getUserInput ();  if  ( i  *  0 )  {  // если i умножить на 0 истинно, добавляем i к сумме. Примечание: НУЛЬ означает ЛОЖЬ, Ненулевое значение означает ИСТИНА. «i * 0» - НУЛЬ (ЛОЖЬ)!  сумма  + =  я ;  // сумма никогда не меняется, потому что (i * 0) равно 0 для любого i; он изменился бы, если бы в условии был! = вместо *  }  if  ( sum  > 100 )  {  перерыв ;  // завершаем цикл; условие выхода существует, но никогда не достигается, потому что сумма никогда не добавляется к  } }

Термин якобы получил свое название от программиста (фамилия Олдерсон), который в 1996 году [12] закодировал модальное диалоговое окно в Microsoft Access без кнопки «ОК» или «Отмена», тем самым отключив всю программу всякий раз, когда это окно появлялось. [13]

См. Также [ править ]

  • Обнаружение цикла
  • Тупик
  • Дивергенция (информатика)
  • Вилочная бомба (бесконечный цикл - один из двух ключевых компонентов)
  • Идти к
  • Рекурсия (информатика)

Внешние ссылки [ править ]

  • Сделайте бесконечный цикл на нескольких языках на сайте programming-idioms.org .

Ссылки [ править ]

  1. ^ "Бесконечное определение словаря цикла" .
  2. ^ «Что такое бесконечный цикл (бесконечный цикл)» .
  3. Дениз Карузо (16 августа 1999 г.). «Перегрузка вешалок создает ухабистую дорогу для интернет-акций» . Нью-Йорк Таймс .
  4. ^ «Кодексы и режимы: характер документальной культуры» . Журнал Flow . Ноябрь 2014. бесконечный цикл - это цикл, в котором отсутствует .. условие выхода.
  5. ^ также известна как многозадачность без вытеснения: «Многозадачность без вытеснения» . Журнал ПК . Проверено 15 августа 2015 года .
  6. Дэвид Хоаг (сентябрь 1976 г.). "История бортового наведения, навигации и управления Apollo" (PDF) . Лаборатория Чарльза Старка Дрейпера.
  7. ^ «Ответы на кроссворды New York Times» . 13 октября 2013 г. вычисление .. дефект .. который .. зациклить
  8. ^ "Проблема остановки в теории вычислений" .
  9. ^ «Использование переполнения буфера против программного обеспечения удаленного управления DameWare» . 19 декабря 2003 г. Как только командная оболочка закрывается комбинацией control-c ...
  10. ^ Программирование на Аде: Управление: бесконечный цикл
  11. ^ «Бесконечный цикл в C / C ++» . Архивировано 3 августа 2016 года.
  12. ^ Ли Dohm (24 мая 2013). «Петля Алдерсона» .
  13. ^ "Петля Олдерсона" . Файл жаргона , версия 4.4.7 . Архивировано 15 мая 2006 года . Проверено 21 мая 2006 .