無限ループ

プログラミングのイディオム

コンピュータプログラミングにおいて無限ループ(またはエンドレスループ[1] [2]とは、スイッチによる電源のオフやプラグの抜き差しなど、外部からの介入がない限り、記述されたとおりに無限に継続する命令列のことである。これは意図的なものである場合もある。

コンピュータ プログラムに無限ループが含まれているかどうかを判断する一般的なアルゴリズムは存在しません。これが停止問題です。

概要

無限ループとは、コンピュータプログラムにおいて、ループを際限なく繰り返す命令列のことである。ループには終了条件がないか、[3]決して満たされない条件があるか、ループを最初からやり直す条件があるために、無限にループする。協調型マルチタスク機能を備えた古いオペレーティングシステムでは、[4]無限ループによってシステム全体が応答しなくなるのが常だった。現在普及しているプリエンプティブマルチタスクモデルでは、無限ループによってプログラムが利用可能なプロセッサ時間をすべて消費してしまうのが常だが、通常はユーザーが終了させることができる。ビジーウェイトループは「無限ループ」と呼ばれることもある。無限ループはコンピュータがハングアップしたりフリーズしたりする原因の1つであるが、その他にもスラッシングデッドロックアクセス違反などが挙げられる

意図的なループと意図しないループ

ループとは、特定の条件が満たされるまで一連の命令を繰り返すことです。ループの固有の特性により、条件が決して満たされない場合に無限ループが発生します。

意図的なループ

この動作が望ましい状況がいくつかあります。例えば、カートリッジベースのゲームコンソールのゲームでは、通常、プログラムが終了できるオペレーティングシステムがないため、メインループに終了条件がありません。ループはコンソールの電源がオフになるまで実行されます。

現代の対話型コンピュータでは、コンピュータがユーザー入力やデバイスの動作を常に監視する必要があるため、根本的なレベルでは、デバイスの電源がオフになるかリセットされるまで継続する無限処理アイドルループが存在します。例えば、アポロ誘導コンピュータでは、この外側のループはExecプログラム[5]に含まれており、コンピュータに他に全く処理する作業がない場合、ダミージョブをループ実行し、「コンピュータ動作」インジケータライトを単に消灯させます。

マルチスレッド

マルチスレッドプログラムでは、一部のスレッドが無限ループ内で実行されていても、プログラム全体が無限ループに陥ることはありません。メインスレッドが終了すると、プロセス内のすべてのスレッドが強制的に停止され、すべての実行が終了し、プロセス/プログラムが終了します。無限ループ内のスレッドは、「ハウスキーピング」タスクを実行することも、(ソケット/キューからの)入力を待機するブロック状態になり、入力を受信するたびに実行を再開することもできます。

意図しないループ

Windows XPブルースクリーンが発生しました。「デバイス ドライバーが無限ループに陥っています。」

ほとんどの場合、この用語は、これが意図した結果ではない場合、つまりバグである場合に使用されます。[6]このようなエラーは初心者プログラマーに最もよく見られますが、原因が非常に微妙な場合があるため、経験豊富なプログラマーでも発生する可能性があります。

例えば、よくある原因の一つとして、プログラマーがリンクリストツリーなどのデータ構造内のノードのシーケンスを反復処理し、各ノードに対してループコードを1回ずつ実行しようとしていることが挙げられます。リンクが不適切に形成されると、データ構造内に参照ループが発生する可能性があります。参照ループとは、あるノードがシーケンス内の前のノードにリンクすることを意味します。これにより、データ構造の一部がリング状になり、単純なコードでは永久にループが発生します。

ほとんどの無限ループはコードを詳しく調べれば発見できますが、特定のプログラムがいつ停止するか、あるいは永遠に実行され続けるかを判断する一般的な方法は存在しません。これが停止問題決定不能性です。[7]

中断

システムが応答している限り、プロセスにシグナル ( Unix のSIGINTなど) を送るか、プロセッサに割り込みを送って現在のプロセスを中止させることで、無限ループを中断できることが多い。これは、タスク マネージャ、端末でControl-Cコマンドを使用する、[8] 、 killコマンドまたはシステム コールを使用することで実行できる。ただし、プロセスがシグナルに応答しないか、プロセッサが割り込み不可能な状態 ( Cyrix の coma バグ(命令パイプラインで割り込み不可能な命令が重複することで発生) にある可能性があるので、この方法は必ずしも機能するわけではない。SIGKILL などの他のシグナルはプロセスが応答する必要がないため機能する場合もあるが、システムをシャットダウンする前までにループを終了できない場合もある。

言語サポート

無限ループは、様々な制御フロー構造を用いて実装できます。非構造化プログラミングでは、最も一般的なのは上方向へのジャンプ(goto )ですが、構造化プログラミングでは、条件を省略するか、明示的にtrueに設定することで、無限ループ(whileループ)を決して終了しないように設定します(例: )while (true) ...

一部の言語では、無限ループのための特別な構造があり、通常は無期限ループから条件を省略します。例としては、Ada ( loop ... end loop)、[9] Fortran ( DO ... END DO)、Go ( for { ... })、Ruby ( loop do ... end)、Rust ( loop { ... }) などがあります。

無限ループは再帰を使って作成することもできます。このプロセスは無限再帰と呼ばれます。

意図的な無限ループの例

これは、 Cで停止せずに「無限ループ」を出力するループです

#include <stdio.h> 

int main () { for (;;) { printf ( "無限ループ\n " ); } return 0 ; }  
      
        
    
     

無限ループの形式はfor (;;)伝統的であり、標準リファレンスの『Cプログラミング言語』にも記載されており、「フォーエバー」と発音されることが多い。[10]breakしかし、を使用して中断したり、を使用して戻ったりreturn、を使用してジャンプしたりすることでループを終了できるため、無限ループが保証されるわけではないgoto

C および C 派生言語では、無限ループはおそらく次のようにより現代的に表現されますwhile (true)

#include <stdio.h> 

int main () { while ( true ) { printf ( "無限ループ\n " ); } return 0 ; }  
      
        
    
     

C++JavaC#などの C の派生言語では、 を使用する方が慣用的ですwhile (true)

1980年代のBASICにおける同様の例:

10印刷"無限ループ" 20 GOTO 10  
  

MS-DOS互換バッチ ファイル での同様の例:

: A 
echo無限ループ
goto  : A

while ループは、条件が常に真であるため、終了することはありません。

ボーン・アゲイン・シェル

for (( ;; )) ; do echo "無限ループ" done  
	 

意図しない無限ループの例

数学的な誤り

以下はVisual Basicにおける無限ループの例です

dim x as integer do while x < 5 x = 1 x = x + 1ループ   
    
    
      

これによりx、ループコードの開始時に にx(以前の値に関係なく)1 が割り当てられ、その後x+ 1 に変更されるため、 が5 を超えることは決してありません。したがって、ループは常に = 2 となり、決して中断されません。この状況は、命令をループの外側に移動し、初期値が一度だけ設定されること xで修正できます。x = 1

一部の言語では、数学記号に関するプログラマの混乱が、意図しない無限ループにつながる可能性があります。例えば、C言語のコード例を以下に示します。

#include <stdio.h> 

int main ( void ) { int a = 0 ; while ( a < 10 ) { printf ( "%d \n " , a ); if ( a = 5 ) { printf ( "a は 5 に等しい! \n " ); } ++ a ; } return 0 ; }  
       
        
         
            
            
        
        
   
    

期待される出力は0から9までの数字で、5と6の間に「aは5に等しい!」という文が挿入されます。しかし、上記の行「 」では、=(代入)演算子と==(等価性テスト)演算子が混同されています。実際には、プログラムのこの時点if (a = 5)では5が代入されてしまいます。そのため、 aは10に進むことができず、ループは終了できません。 aa

丸め誤差

AMD Turionプロセッサの C 出力:
x = 0.10000000149011611938
x = 0.20000000298023223877
x = 0.30000001192092895508
x = 0.40000000596046447754
x = 0.50000000000000000000
x = 0.60000002384185791016
x = 0.70000004768371582031
x = 0.80000007152557373047
x = 0.90000009536743164062
x = 1.00000011920928955078
x = 1.10000014305114746094
x = 1.20000016689300537109
...

終了条件の評価における予期せぬ動作も、この問題の原因となる可能性があります。C言語の例を以下に示します

float x = 0.1 ; while ( x != 1.1 ) { printf ( "x = %22.20f \n " , x ); x += 0.1 ; }   
    
     
      

一部のシステムでは、このループは期待通りに10回実行されますが、他のシステムでは終了しません。問題は、ループの終了条件が2つの浮動小数点(x != 1.1)値が完全に等しいかどうかをテストすることです。多くのコンピュータにおける浮動小数点値の表現方法では、このテストは失敗します。なぜなら、浮動小数点値は0.1という値を正確に表現できず、各インクリメントで丸め誤差が生じるからです(ボックス参照)。

Pythonでも同じことが起こります

x :  float  =  0.1 
、x != 1 の場合 : print ( x ) x += 0.1  
    
      

等価性または非等価性のテストが予期せず失敗する可能性があるため、浮動小数点値を扱う際には、より大きいかより小さいかのテストを使用する方が安全です。例えば、 が 1.1 と等しいかどうかをテストする代わりに、 、 、 のいずれかかどうかxをテストできます。どちらの場合も、有限回数の反復処理後に必ず終了します。この特定の例を修正する別の方法は、実行された反復処理の回数をカウントする 整数 をループインデックスとして使用することです。(x <= 1.0)(x < 1.1)

数値解析においても同様の問題が頻繁に発生します。特定の結果を計算するために、誤差が所定の許容値より小さくなるまで反復計算を実行する必要があります。しかし、反復計算中に発生する丸め誤差により、指定された許容値に決して到達できず、無限ループに陥ってしまうのです。

マルチパーティループ

無限ループは、複数のエンティティの相互作用によって発生する可能性があります。リクエストを理解できない場合、常にエラーメッセージを返すサーバーを考えてみましょう。サーバー自体には無限ループが発生する可能性がなくても、2つのサーバー( AB)で構成されるシステムでは、無限ループが発生する可能性があります。ABから不明なタイプのメッセージを受信した場合AはBにエラーメッセージを返信します。Bがエラーメッセージを理解できない場合、 Bは独自のエラーメッセージをAに返信します。ABからのエラーメッセージを理解できない場合、Aはさらに別のエラーメッセージを送信します。といった具合です。

このような状況のよくある例として、メールループが挙げられます。メールループの一例として、返信不可の受信トレイからメールを受信したものの、自動返信がオンになっている場合が挙げられます。返信不可の受信トレイに返信すると、「これは返信不可の受信トレイです」というメッセージが送信されます。このメッセージがユーザーに送信され、さらにユーザーが返信不可の受信トレイに自動返信を送信する、といった状況が繰り返されます。

疑似無限ループ

疑似無限ループとは、無限のように見えるが、実際には非常に長いループであるループです。

不可能な終了条件

Cfor ループの:

(符号なし整数i = 1 ; i != 0 ; i ++ ) { }          

これは無限に続くように見えますが、実際には の値はi最終的に に格納できる最大値に達しunsigned int、その数値に1を加えると がラップアラウンドして整数オーバーフローが発生し、ループが中断されます。 の実際の限界は、使用するシステムとコンパイラiの詳細によって異なります任意精度演算では、このループはコンピュータのメモリがを保持できなくなるまで続きますが符号なし整数ではなく符号付き整数の場合、オーバーフローは未定義になります。 ii

参照

参考文献

  1. ^ 「Endless loop dictionary definition」. 2020年8月1日時点のオリジナルよりアーカイブ2020年1月22日閲覧。
  2. ^ “無限ループ(エンドレスループ)とは”. 2019年7月15日時点のオリジナルよりアーカイブ2020年1月22日閲覧。
  3. ^ 「コードとモード:ドキュメンタリー文化の特徴」Flow Journal、2014年11月。2020年8月1日時点のオリジナルよりアーカイブ。 2020年1月23日閲覧無限ループとは、終了条件が欠如しているループのことである。
  4. ^ 非プリエンプティブマルチタスクとも呼ばれる:「非プリエンプティブマルチタスク」。PC Magazine。2019年7月26日時点のオリジナルよりアーカイブ。 2024年2月7日閲覧
  5. ^ David Hoag (1976年9月). 「アポロ宇宙船搭載誘導・航法・管制の歴史」(PDF) . Charles Stark Draper Laboratory. 2016年11月5日時点のオリジナルよりアーカイブ(PDF) . 2020年1月23日閲覧
  6. ^ 「ニューヨーク・タイムズ・クロスワード・アンサーズ」、2013年10月13日。2020年8月2日時点のオリジナルよりアーカイブ。 2020年1月22日閲覧コンピューティング…欠陥…ループする
  7. ^ “Halting Problem in Theory of Computation”. 2018年10月3日. 2020年8月9日時点のオリジナルよりアーカイブ。 2020年1月22日閲覧
  8. ^ 「DameWareリモートコントロールソフトウェアに対するバッファオーバーフロー攻撃」2003年12月19日。2020年7月24日時点のオリジナルよりアーカイブ。 2020年1月22日閲覧。Ctrl + Cキーの組み合わせでコマンドシェルを閉じるとすぐに…
  9. ^ Adaプログラミング:制御:無限ループ
  10. ^ 「C/C++における無限ループ」。2016年8月3日時点のオリジナルよりアーカイブ。
  • programming-idioms.org で、いくつかの言語で無限ループを作成します。
「https://en.wikipedia.org/w/index.php?title=Infinite_loop&oldid=1330772781」から取得