メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

到達不能コード

先行する制御フロー ステートメントが原因で実行されないコード

説明

この欠陥は、次のいずれかのステートメントを使用した制御フロー内の break が原因で、コードのセクションに到達できなかった場合に発生します。

  • break および return:breakreturn などのステートメントは、プログラムのフローを別のセクションまたは関数に移します。このフローのエスケープにより、フロー制御コードに続くステートメントは実行できず、したがってステートメントは到達不能になります。

  • goto:goto などのステートメントは、プログラムのフローをコードの別のセクションにジャンプさせます。goto の直後にあるステートメントに戻るジャンプがない場合、このようなステートメントは実行できません。

  • while(1):while(1) などのトリビアルな無限ループでは、プログラムの終了によってプログラムのフローが解放されます。このタイプの終了は、無限ループの後に来るコードが到達不能になる原因となります。

リスク

到達不能コードは開発時間、メモリ、および実行サイクルを浪費します。開発者は実行されないコードを保守しなければなりません。実行されない命令でも保存およびキャッシュされる必要があります。

修正方法

修正方法は到達不能コードの意図する機能によって異なります。そのコードを実行する場合、コードの配置または制御フローを変えている先行ステートメントの配置をチェックします。たとえば、到達不能コードが return ステートメントの後にある場合、それらの順序を入れ替えるか、その return ステートメント全体を削除しなければならない可能性があります。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

すべて展開する

typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void guess(suit s);

suit deal(void){
    suit card = nextcard();
    if( (card < SPADES) || (card > CLUBS) ) 
        card = UNKNOWN_SUIT;
        return card;

    if (card < HEARTS) {
        guess(card);
    }
    return card;
}

この例では、1 番目の if ブロックに中かっこが欠落しています。その結果、関数 deal() のすべての実行コンテキストにおいて、1 番目の return ステートメントは、その関数が呼び出された箇所にコードのフローを戻します。この return ステートメントのために、2 番目の if ブロックおよび 2 番目の return ステートメントは実行できません。

インデントと中かっこの修正を行うと、エラーが明確になります。

typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void guess(suit s);

suit deal(void){
    suit card = nextcard();
    if( (card < SPADES) || (card > CLUBS) ){ 
        card = UNKNOWN_SUIT;
    }
    return card;

    if (card < HEARTS) {
        guess(card);
    }
    return card;
}

修正 — return の削除

1 つの修正方法として、escape ステートメントを削除します。この例では、最初の return ステートメントを削除して、最後の if ステートメントに到達します。

typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void guess(suit s);

suit deal(void){
    suit card = nextcard();
    if( (card < SPADES) || (card > CLUBS) )
    {
        card = UNKNOWN_SUIT;
    }

    if(card < HEARTS)
    {
        guess(card);
    }
    return card;
}
修正 — 到達不能コードの削除

別の修正方法として、必要でなければ到達不能コードを削除します。関数は 2 番目の if ステートメントに到達しないため、これを削除するとコードが単純になり、しかもプログラムの動作は変更されません。

typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void guess(suit s);

suit deal(void){
    suit card = nextcard();
    if( (card < SPADES) || (card > CLUBS) )
    {
        card = UNKNOWN_SUIT;
    }
    return card;
}
int add_apples(int apple) { 
    int count = 1;
    while(1) {
        if(apple < 99){
            apple++; 
            count++;
        }else{
            count--;
        }
    }
    return count;
}

この例では、while(1) ステートメントにより無限ループが形成されています。この無限ループを終了させる方法はプログラムの終了のみであるため、この無限ループの後に来る return count は到達不能になります。

修正 — ループ条件の書き換え

1 つの修正方法として、ループ条件を変更して while ループを有限にします。ここでの修正例では、if の条件 apple < 99 から構成したステートメントがループで使用されます。

int add_apples1(int apple) { 
    int count = 0;
    while(apple < 99) { 
        apple++; 
        count++;
    }
    if(count == 0)
        count = -1;
    return count;
}
修正 — break ステートメントを追加

別の修正方法として、無限ループからのブレークポイントを追加し、無限ループの後に来るコードへの到達を可能にします。この例では、breakelse ブロックに追加され、return count ステートメントが到達可能になっています。

int add_apples(int apple) { 
    int count = 1;
    while(1) {
        if(apple < 99)
        {
            apple++; 
            count++;
        }else{
            count--;
            break;
        }
    }
    return count;
}
修正 — 到達不能コードの削除

別の修正方法として、到達不能コードを削除します。この修正によりコードがクリーンアップされ、確認と保守が容易になります。この例では、return ステートメントを削除し、関数の戻り値の型を void に変更しています。

void add_apples(int apple) { 
    int count = 1;
    while(1) {
        if(apple < 99)
        {
            apple++; 
            count++;
        }else{
            count--;
        }
    }
}

結果情報

グループ: データ フロー
言語: C | C++
既定値: オン
コマンド ライン構文: UNREACHABLE
影響度:Medium

バージョン履歴

R2013b で導入