MSC07-C. デッドコードを検出して削除する
実行されることがないコードのことをデッドコードと呼ぶ。一般的には、デッドコードが存在するということは、プログラム自身やプログラム環境が変化したために論理エラーが生じたことを示している。デッドコードは通常、コンパイル時に最適化によってプログラムから除外される。しかし、読みやすさを改善し、論理エラーを確実に解決するために、デッドコードを特定し、理解し、排除する必要がある。
このレコメンデーションは「MSC12-C. プログラムに対して作用を及ぼさないコードを検出して削除する」に関連している。
違反コード
以下のコード例は、デッドコードがプログラム内で発生する様子を示している [Fortify 06]。2 番目の条件文 if (s) は決して真にはならない。真になるためには、s に NULL が代入されないことが要求されるが、s に NULL 以外の値が代入される唯一の経路が、return 文で終了しているためである。
int func(int condition) { char *s = NULL; if (condition) { s = (char *)malloc(10); if (s == NULL) { /* エラー処理 */ } /* s の処理 */ return 0; } /* ... */ if (s) { /* このコードには到達することがない */ } return 0; }
適合コード
デッドコードを修正するには、プログラマはコードがなぜ実行されないのかを突き止め、その状況に適切に対処する必要がある。上記のコード例を修正するには、最初の条件文の本体から return を削除する。
int func(int condition) { char *s = NULL; if (condition) { s = (char *)malloc(10); if (s == NULL) { /* エラー処理 */ } /* s の処理 */ } /* ... */ if (s) { /* このコードに到達できるようになった */ } return 0; }
違反コード
以下のコード例では、strlen() 関数を使用して、関数 string_loop() の反復回数を制限している。ループ内の条件文は、文字列内の現在の文字が null 終端文字の場合に真として評価される。しかし、strlen() は null 終端文字より前の文字数を返すため、条件文が真になることはない。
int string_loop(char *str) { size_t i; size_t len = strlen(str); for (i=0; i < len; i++) { /* ... */ if (str[i] == '\0') /* このコードには到達することがない */ } return 0; }
適合コード
デッドコードの削除方法はプログラマの意図により異なる。以下のコードでは、null 終端文字の直前の文字を処理することを意図していると仮定し、i が null 終端文字の直前の文字を指していることを正しく判定できる条件文としている。
int string_loop(char *str) { size_t i; size_t len = strlen(str); for (i=0; i < len; i++) { /* ... */ if (str[i+1] == '\0') /* このコードに到達した */ } return 0; }
例外
MSC07-EX1: 場合によっては、デッドコードによって将来の変更にプログラムが対応しやすくなることもある。たとえば、switch 文の制御式が取り得る値がすべてラベルとして指定されているところに default ラベルを追加する場合が挙げられる(この例の説明は、「MSC01-C. 論理的な完全性を追求する」を参照)。
MSC07-EX2: あとから必要になる可能性があるコードは、コメントアウトによる削除でもよい(説明は「MSC04-C. コメントは一貫性を持たせ読みやすくする」を参照)。
リスク評価
デッドコードの存在は、意図しないプログラム動作につながる論理エラーを示している場合がある。プログラム内でデッドコードが発生する仕組みや、それを除去する方法は複雑である。それゆえ、デッドコードの解消は大量の解析を必要とする込み入った作業になる可能性がある。
レコメンデーション | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
MSC07-C | 低 | 低 | 中 | P2 | L3 |
自動検出
LDRA tool suite Version 7.6.0 はこのレコメンデーションの違反を検出できる。
Splint Version 3.1.1 はこのレコメンデーションの違反を検出できる。
GCC 4.4.0 は、-Wunreachable-code フラグが使用されているときにこのレコメンデーションの違反を検出できる。
Klocwork Version 8.0.4.16 は、LV_UNUSED.DEAD、PA_UNUSED.DEAD、UNREACH.BREAK、UNREACH.GEN、UNREACH.RETURN、および UNREACH.RETURN0 チェッカーを使ってこのレコメンデーションの違反を検出できる。
参考情報
- [Fortify 06] Code Quality, "Dead Code"
- [ISO/IEC PDTR 24772] "BRS Leveraging human experience," "BVQ Unspecified Functionality," and "XYQ Dead and Deactivated Code"
- [MISRA 04] Rule 2.4
- [MITRE 07] CWE ID 561, "Dead Code"
翻訳元
これは以下のページを翻訳したものです。