メインコンテンツ

オーバーフロー チェックのレビューと修正

このトピックでは、Polyspace® Code Prover™[オーバーフロー] チェックの結果を体系的にレビューする方法を説明します。

[オーバーフロー] チェックの修正を判断するまでこれらの手順の 1 つ以上に従います。このチェックを修正する方法は複数あります。チェックおよびコードの例については、オーバーフローを参照してください。

特にオレンジ チェックに対して、チェックが実際のエラーを表すのではなく、コードに該当しない Polyspace 前提条件を表していると判定できます。前提条件を緩和するのに解析オプションを使用できる場合、そのオプションを使用して検証を再実行します。それ以外の場合は、結果またはコードにコメントおよび正当化情報を追加できます。

すべてのチェックに適用される一般的なワークフローについては、Polyspace デスクトップ ユーザー インターフェイスでの Code Prover の結果の解釈またはPolyspace Access Web インターフェイスでの Code Prover の結果の解釈 (Polyspace Access)を参照してください。

手順 1: チェック情報の解釈

カーソルをオーバーフローが発生する演算の上に置きます。

Cursor placed over an operation that overflows with the tooltip showing for the check.

ツールヒントから次の情報を取得します。

  • オーバーフローを回避するために制約可能なオペランド変数。

    前述の例では、左側のオペランド val には全範囲の値が含まれています。

    考えられる解決方法: オーバーフローを回避するには、val が特定の範囲にある場合のみ乗算を実行します。

    if(val < INT_MAX/2)
        return(val*2);
    else 
        /* Alternate action */
  • オーバーフローについて考えられる根本原因 (ツールヒントに示されている場合)。

    前述の例では、スタブ関数 getVal が考えられる原因として識別されています。

    考えられる解決方法: オーバーフローを回避するには、getVal の戻り値を制約します。たとえば、getVal1..10 などの特定の範囲内で値を返すよう指定します。詳細については、スタブ関数に関する Code Prover の仮定を参照してください。

手順 2: チェックの根本原因の判定

制約するオペランド変数から開始してデータ フローをトレースします。制約を指定するのに適したポイントを特定します。

次の例では、tempVal から開始してデータ フローをトレースします。

val = func();
.
.
tempVal = val;
.
.
tempVal++ ;
この例では、以下のような場合があります。

  1. tempValval から全範囲の値を取得しています。

    考えられる解決方法: val が特定の値未満である場合のみ、valtempVal に割り当てます。

  2. valfunc から全範囲の値を取得しています。

    考えられる解決方法: func がスタブされている場合、func の戻り値を func の本体内または Polyspace の [制約指定] インターフェイスで制約します。詳細については、スタブ関数に関する Code Prover の仮定を参照してください。

データ フローをトレースするには、チェックを選択し、[結果の詳細] ペインの情報を確認します。

  • [結果の詳細] ペインでチェックにつながる命令の順序が表示される場合、各命令を選択します。

  • [結果の詳細] ペインに、そのチェックの考えられる原因の行番号が表示される場合、[ソース] ペインを右クリックします。[行に移動] を選択します。

  • そうしない場合は、次のようになります。

    1. オペランド変数の前の書き込み操作を検索します。

      例: tempVal の前の書き込み操作は tempVal=val です。

    2. 前の書き込み操作で、逆にトレースするために新しい変数を特定します。

      書き込み操作に含まれる変数の上にカーソルを置き、その値を確認します。これらの値は、トレースする変数を判断する際に役立ちます。

      例: tempVal=val では、val は全範囲の値を取ることがわかります。したがって、val をトレースします。

    3. 新しい変数の前の書き込み操作を検索します。制約を指定するポイントを特定するまでこの方法で逆にトレースを続行します。

      例: val の前の書き込み操作は val=func() です。func の戻り値に対する制約を指定するように選択できます。

変数に応じて、以下のナビゲーション ショートカットを使用し、前のインスタンスを検索します。以下の手順は、Polyspace ユーザー インターフェイスでのみ実行できます。

変数変数の前のインスタンスの検索方法

ローカル変数

次のいずれかの方法を使用してください。

  • 変数の検索。

    1. 変数を右クリックします。[すべての参照を検索] を選択します。

      変数のすべてのインスタンスは、現在のインスタンスが強調表示されて [検索] ペインに表示されます。

    2. [検索] ペインで前のインスタンスを選択します。

  • ソース コードの参照。

    1. [ソース] ペインで変数をダブルクリックします。

      変数のすべてのインスタンスは強調表示されます。

    2. 上にスクロールして前のインスタンスを検索します。

グローバル変数

変数を右クリックします。オプション [変数アクセス ビューで表示] が表示される場合、変数はグローバル変数です。

  1. オプション [変数アクセス ビューで表示] を選択します。

    [変数アクセス] ペインでは、変数の現在のインスタンスが表示されます。

  2. このペインで、変数の前のインスタンスを選択します。

    変数の書き込み操作は write opterations arrow icon で示され、読み取り操作は read operations arrow icon で示されます。

関数の戻り値

ret=func();

  1. 関数定義を検索します。

    [ソース] ペインの func を右クリックします。オプションが存在する場合、[定義に移動] を選択します。Polyspace で定義を利用できない場合は、オプションを選択すると関数宣言に移動します。

  2. func の定義では、各 return ステートメントを特定します。関数が返す変数が逆にトレースするための新しい変数です。

任意の操作に含まれる変数が前の操作に関連しているかどうかを判断することもできます。コード内の変数間の関係の検出を参照してください。

ヒント

整数オーバーフローと浮動小数点のオーバーフローを区別するには、[結果の詳細] ペインの [詳細] 列を使用します。列ヘッダーをクリックして、整数オーバーフローと浮動小数点のオーバーフローをグループ化します。[詳細] 列が表示されていない場合は、他の列ヘッダーを右クリックして、この列を有効にします。

手順 3: チェックの一般的な原因の検索

オーバーフローの原因となる演算がループ内または再帰関数の本体内で発生する場合、次の手順に従います。

  • ループの実行または再帰の数を減らすことができるか確認します。

  • 演算のオーバーフローの前で、ループまたは再帰関数内に終了条件を置けるかどうかを確認します。

手順 4: Polyspace の前提条件へのチェックをトレース

コードの前方で発生する Polyspace 前提条件にオレンジ チェックをトレースできるかどうかを確認します。前提条件があてはまらない場合、結果またはコードにコメントまたは正当化情報を追加します。Polyspace ユーザー インターフェイスでのバグ修正または正当化による結果への対処またはPolyspace Access でのバグ修正または正当化による結果への対処 (Polyspace Access)を参照してください。

たとえば、コード内で volatile 変数を使用しているとします。ここで、次のようにします。

  1. Polyspace は、volatile 変数がコード内の各ステップで全範囲であると仮定します。

  2. その変数を使用する演算はオーバーフローする可能性があり、そのため、オレンジになります。

  3. 変数が値がより小さな範囲を取るとわかっている場合、コードにコメントおよび正当化情報を追加し、コードを変更しなかった理由を説明します。

詳細については、Code Prover 解析の前提条件を参照してください。

メモ

オレンジ チェックを正当化する前に、コード設計を改善できるかどうかを十分に検討してください。