到達不能コードとは
到達不能コードとは、プログラムの一部として存在しているにもかかわらず、実行されることが決してないコードのことです。例えば、
機械語プログラムにおいて、プログラムカウンタがそのアドレスに到達することがない場合、そのコードは到達不能となります。これは、プログラムの制御フロー上、そのコードにたどり着く経路が存在しないことを意味します。
到達不能コードの問題点
到達不能コードは、以下のような理由から好ましくありません。
バグの潜在: プログラマが、あるコードが実行されると誤って認識している場合、実際には実行されないことは、本来必要な処理が行われていないというバグの可能性を示唆します。
保守性の低下: 到達不能コードは、作者以外には理解が難しく、メンテナンスを困難にします。
無駄なコード: 到達不能コードは、プログラムの実行に影響を与えないため、無駄なコードとしてプログラムのサイズを肥大化させる可能性があります。
到達不能コードは、デッドコードの一種であり、冗長なコードや使われない変数などもデッドコードに含まれます。
到達不能コードの検出
到達不能コードは、静的コード解析によって検出することができます。静的コード解析では、変数の値や実行時の条件に関わらず、決して実行されないコードを制御構造の分析や抽象解釈を用いて特定します。また、一部のプログラミング言語では、到達不能コードが言語仕様上許容されない場合もあります。
ただし、静的解析で検出できるのは、比較的単純なパターンの到達不能コードに限られます。より複雑なケースでは、実行時の動的な最適化やプロファイラを用いた検出が必要になる場合があります。
到達不能コードが生まれる原因
到達不能コードが生じる原因は様々ですが、主なものとして以下のようなものが挙げられます。
一時的な修正: プログラマが一時的にコードの実行を抑制するために、コードを書き換えた結果、到達不能コードが残ってしまうことがあります。例えば、
デバッグのために一時的に関数呼び出しをコメントアウトしたり、条件文を書き換えたりした場合です。
冗長な条件判断: 条件判断が重複していたり、常に真または偽となる条件式が存在する場合、到達不能コードが生じる可能性があります。
デバッグ用コードの残存:
デバッグ用に挿入したコードを削除し忘れた場合、到達不能コードとなることがあります。
関数呼び出しの変更: 関数やサブルーチンがどこからも呼び出されなくなったり、到達不能コードからのみ呼び出されている場合、デッドコードとなります。
プログラムの前提や環境の変更: プログラムの前提条件や実行環境が大きく変わった場合、以前は実行されていたコードが到達不能になることがあります。
到達不能性の検証
任意のコードが到達不能かどうかを完全に判断することは、
停止性問題と同等であり、一般には不可能です。しかし、静的解析技術の進歩により、到達不能コードの検出精度は向上しています。
プロファイラは、コードの実行頻度を測定することで、到達不能コードの発見を支援することができます。疑わしい部分が見つかった場合は、より強力な解析ツールや人間による検証が必要になります。
到達不能コードと脆弱性
到達不能コードが原因で、重大な脆弱性が生まれることがあります。有名な例として、
AppleのTLS/SSL実装における「goto fail bug」があります。この
バグは、2つ連続した`goto fail;`文のうち、2つ目の`goto fail;`文によって、本来実行されるべきチェック処理が到達不能になり、セキュリティ上の脆弱性が発生しました。
まとめ
到達不能コードは、プログラムの品質を低下させるだけでなく、セキュリティ上の脆弱性につながる可能性もあります。プログラマは、常に到達不能コードの発生に注意し、静的解析ツールやプロファイラなどを活用して、早期に発見・修正することが重要です。また、到達不能コードが発生した場合は、その原因を追求し、再発防止に努めるべきです。