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

В компьютерном программировании , в бесконечном цикле (или бесконечный цикл ) [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, как 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) ;  возврат  0 ;}

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

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

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

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

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

: A echo Infinite Loop goto  : A

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

Пример на Java

в то время как  ( истина )  System . из . println ( «Бесконечный цикл» );

Пример в Bourne Again Shell

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

Пример в Rust

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

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

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

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

dim  x  как  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]

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

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

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

  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 .

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

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