メインコンテンツ

CWE Rule 570

Expression is Always False

R2023a 以降

説明

ルールの説明

The software contains an expression that will always evaluate to false.

Polyspace 実装

ルール チェッカーは以下の問題をチェックします。

  • 条件が常に false であるために非アクティブにされたコード

  • デッド コード

すべて展開する

問題

この問題は、コードのブロックが #if 0 命令または if(0) 条件を使用して非アクティブにされた場合に発生します。

リスク

#if 0 命令または if(0) 条件を使用して、コードのセグメントを一時的に非アクティブにしています。量産コードにこれらの命令が含まれている場合、コードをリリースする前に非アクティブ化が解除されていないことを意味します。

修正方法

コードのセグメントがデバッグのみを目的としている場合、量産コードからそのセグメントを削除します。非アクティブ化が意図せず発生した場合は、#if 0 ステートメントと #endif ステートメントを削除します。

多くの場合、コードのセグメントは特定のオペレーティング システムなど特定の条件で非アクティブ化されます。これらの条件を示すには、#if 0 命令を使用してコードを完全に非アクティブ化するのではなく、#if 命令を含むマクロを使用します。たとえば、GCC では、Windows® オペレーティング システムを検出するマクロが用意されています。

#ifdef _WIN32
   //Code deactivated for all operating systems
   //Other than 32-bit Windows
#endif

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

例 — 条件が常に false であるために非アクティブにされたコード エラー
#include<stdio.h>
int Trim_Value(int* Arr,int Size,int Cutoff) 
{
    int Count=0;

    for(int i=0;i < Size;i++){
        if(Arr[i]>Cutoff){
            Arr[i]=Cutoff;
            Count++;
        }
    }

    #if 0 //Noncompliant
    /* Defect: Code Segment Deactivated */

    if(Count==0){
        printf("Values less than cutoff.");
    }
     #endif

    return Count;
}

上記のコードでは、printf ステートメントが #if #endif 命令内に置かれています。ソフトウェアは命令内のポーションをコード コメントでありコンパイルされていないものとして扱います。

修正 — #if 0#if 1 に変更

printf ステートメントを非アクティブにするのではない場合、1 つの修正方法として、#if #endif 命令内のコードのブロックを再度アクティブにできます。ブロックを再度アクティブにするには、#if 0#if 1 に変更します。

#include<stdio.h>
int Trim_Value(int* Arr,int Size,int Cutoff) 
{
 int Count=0;

 for(int i=0;i < Size;i++)
     {
      if(Arr[i]>Cutoff)
            {
             Arr[i]=Cutoff;
             Count++;
            }
     }


 /* Fix: Replace #if 0 by #if 1 */	  
 #if 1  
      if(Count==0)
           {
            printf("Values less than cutoff.");
           }
 #endif

 return Count;
}
問題

この問題は、常に true または false になる条件が原因でコードのブロックに到達できない場合に発生します。この欠陥は以下を除外します。

  • Code deactivated by constant false condition: #if 0 または if(0) などのコンパイル時の定数を使用する命令をチェックする。

  • Unreachable code: gotobreakreturn などのコントロール エスケープ後のコードをチェックする。

  • Useless if: ステートメントが常に true であるかどうかをチェックする。

リスク

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

デッド コードは多くの場合、使用されることのないレガシ コードを表します。デッド コードを定期的にクリーン アップすると、将来の保守の負担が減ります。

修正方法

修正方法は欠陥の根本原因によって異なります。たとえば、同じ実行パスで 2 回チェックされるエラー状態が根本原因で、2 回目のチェックが冗長であるため、対応するブロックがデッド コードになっている可能性があります。

多くの場合、結果の詳細 (または Polyspace as You Code のソース コード ツールヒント) には欠陥につながる一連のイベントが表示されます。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して、欠陥に関連する変数のこれまでの参照を検索し、関連するイベントを検出できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈またはPolyspace Access Web インターフェイスでの Bug Finder の結果の解釈 (Polyspace Access)も参照してください。

以下の修正例を参照してください。

isinfisnan などの関数の使用でデッド コードが表示された場合、非有限値を考慮に入れる解析モードを有効にします。詳細は、非有限の浮動小数点を検討 (-allow-non-finite-floats) を参照してください

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

例 — if ステートメントのデッド コード
#include <stdio.h>

int Return_From_Table(int ch){

    int table[5];

    /* Create a table */
    for(int i=0;i<=4;i++){
        table[i]=i^2+i+1;
    }

    if(table[ch]>100){ //Noncompliant
         return 0;  
    }
    return table[ch];
}

配列 table 内の最大値は 4^2+4+1=21 であるため、テスト式 table[ch]>100 は常に false として評価されます。if ステートメント内の return 0 は実行されません。

修正 — デッド コードを削除

1 つの修正方法として、if 条件をコードから削除することができます。

#include <stdio.h>

int Return_From_Table(int ch){

    int table[5];

    /* Create a table */
    for(int i=0;i<=4;i++){
        table[i]=i^2+i+1;
    }

    return table[ch];
}
例 — 列挙型を含む if のデッド コード
typedef enum _suit {UNKNOWN_SUIT, SPADES, HEARTS, DIAMONDS, CLUBS} suit;
suit nextcard(void);
void do_something(suit s);

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

    if (card > 7) {  //Noncompliant
        do_something(card);
    }
}

suit 型は 5 つのオプションで列挙されます。ただし、条件式 card > 7card の最大値が 5 であるため常に false と評価されます。if ステートメント内の内容は実行されません。

修正 — 条件の変更

1 つの修正方法としてコードの if 条件を変更することができます。この修正では、7 は HEART に変更され、card 型に直接関連付けます。

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

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

    if (card > HEARTS) {
        do_something(card);
    }
}

チェック情報

カテゴリ: Expression Issues

バージョン履歴

R2023a で導入