到達不能コード

出典: フリー百科事典『ウィキペディア(Wikipedia)』

これはこのページの過去の版です。RedBot (会話 | 投稿記録) による 2011年12月28日 (水) 13:05個人設定で未設定ならUTC)時点の版 (r2.7.1) (ロボットによる 変更: de:Unerreichbarer Code)であり、現在の版とは大きく異なる場合があります。

到達不能コード(とうたつふのうコード、: unreachable code)またはデッドコード: dead code)は、プログラムのソースコードに存在するものの、決して実行されないコードを指す。

デッドコードは以下のような理由から好ましくないとされる。

  • 作者がそのコードが実行されると思っていた場合、そのプログラムにはバグが存在する。
  • 作者や保守者がそのコードが実行されないことを見逃していた場合、保守に際して時間と労力を無駄に費やすことになる。

冗長コードは、実行はされるがプログラムの出力に何の影響も与えないコードである。宣言されても使われない識別子は冗長宣言などと呼ばれる。

到達不能コードの検出

デッドコードの検出は静的コード解析の一種であり、変数の値やその他の実行時の条件がどうであっても決して実行されないコードを制御構造を分析することで検出する。一部の言語(Javaなど)では、ある種の到達不能コードは言語の仕様上許容されない。デッドコードを削除する最適化手法をデッドコード削除と呼ぶ。

コンパイラ最適化の結果としてコードが到達不能になることもある(共通式削除など)。

到達不能コードが生まれる原因

以下では、ソースコードに到達不能コードが生じる原因をいくつか解説する。

ソフトウェア開発の際、プログラマは一時的にコードが実行されないようにすることがある(すなわち、明示的に実行されないように書き換える)。例えば、次のようなコードがある。

 while (condition)
 {
   foo();
   bar();
 }

ここで、一時的に bar() を実行しないようにしたい場合、例えば次のように書き換える。

 while (condition)
 {
   foo();
   continue;
   bar();
 }

この例では、bar() が到達不能コードになる(continue はループの次の反復に直ちに移行させる)。このような一時的な修正がリリース時まで残ってしまうことがある。

他の到達不能コードが生じる原因として、条件判断が冗長化している場合や、デバッグ用コードを削除せずに残してしまう場合がある。

関数やサブルーチンは、どこからも呼び出されない場合はデッドコードになるし、到達不能コードからのみ呼び出されている関数もデッドコードになる。

到達不能コードの存在は、プログラムの修正時の論理的誤りや、プログラムの前提や環境が大幅に変更されたことを示す場合もある。優れたコンパイラはデッドコードの存在を通知し、保守者がその意味を考えられるようにする。

到達不能性の検証

任意のコードが到達不能コードかどうかを判断することは停止性問題を解くことと等価である。すなわち、あらゆる到達不能コードを正しく把握することは不可能である。

実際には分析手法は精巧化しており、到達不能コードを検出する量は大幅に改善されている。例えば以下のコードで、定数畳み込みや単純なフロー解析では、xyz という文が到達不能であることを示すことができる。

 int n = 2 + 1;
 if (n == 4)
 {
   xyz
 }

しかし、以下のコードで xyz という文が到達不能であることを検出するにはかなりの努力を要する。

 double x = sqrt(2);
 if (x > 2)
 {
   xyz
 }

到達不能性とプロファイリング

場合によっては、静的コード解析による通常の手法と同時に、プロファイラを使って複雑なケースを検出できる場合もある。プロファイラはコードの到達不能性を「証明」できるわけではないが、到達不能コードを見つけ出すヒューリスティクスとしては優れている。疑わしい部分が見つかったら、もっと強力な分析ツールを使ったり、人間が目と手で調査して、そのコードが本当に到達不能かどうかを判断する。

関連項目