オーバーフロー チェックのレビューと修正
このトピックでは、Polyspace® Code Prover™ で [オーバーフロー] チェックの結果を体系的にレビューする方法を説明します。
[オーバーフロー] チェックの修正を判断するまでこれらの手順の 1 つ以上に従います。このチェックを修正する方法は複数あります。チェックおよびコードの例については、オーバーフロー
を参照してください。
特にオレンジ チェックに対して、チェックが実際のエラーを表すのではなく、コードに該当しない Polyspace 前提条件を表していると判定できます。前提条件を緩和するのに解析オプションを使用できる場合、そのオプションを使用して検証を再実行します。それ以外の場合は、結果またはコードにコメントおよび正当化情報を追加できます。
すべてのチェックに適用される一般的なワークフローについては、Polyspace デスクトップ ユーザー インターフェイスでの Code Prover の結果の解釈またはPolyspace Access Web インターフェイスでの Code Prover の結果の解釈 (Polyspace Access)を参照してください。
手順 1: チェック情報の解釈
カーソルをオーバーフローが発生する演算の上に置きます。
ツールヒントから次の情報を取得します。
オーバーフローを回避するために制約可能なオペランド変数。
前述の例では、左側のオペランド
val
には全範囲の値が含まれています。考えられる解決方法: オーバーフローを回避するには、
val
が特定の範囲にある場合のみ乗算を実行します。if(val < INT_MAX/2) return(val*2); else /* Alternate action */
オーバーフローについて考えられる根本原因 (ツールヒントに示されている場合)。
前述の例では、スタブ関数
getVal
が考えられる原因として識別されています。考えられる解決方法: オーバーフローを回避するには、
getVal
の戻り値を制約します。たとえば、getVal
が1..10
などの特定の範囲内で値を返すよう指定します。詳細については、スタブ関数に関する Code Prover の仮定を参照してください。
手順 2: チェックの根本原因の判定
制約するオペランド変数から開始してデータ フローをトレースします。制約を指定するのに適したポイントを特定します。
次の例では、tempVal
から開始してデータ フローをトレースします。
val = func();
.
.
tempVal = val;
.
.
tempVal++ ;
tempVal
はval
から全範囲の値を取得しています。考えられる解決方法:
val
が特定の値未満である場合のみ、val
をtempVal
に割り当てます。val
はfunc
から全範囲の値を取得しています。考えられる解決方法:
func
がスタブされている場合、func
の戻り値をfunc
の本体内または Polyspace の [制約指定] インターフェイスで制約します。詳細については、スタブ関数に関する Code Prover の仮定を参照してください。
データ フローをトレースするには、チェックを選択し、[結果の詳細] ペインの情報を確認します。
[結果の詳細] ペインでチェックにつながる命令の順序が表示される場合、各命令を選択します。
[結果の詳細] ペインに、そのチェックの考えられる原因の行番号が表示される場合、[ソース] ペインを右クリックします。[行に移動] を選択します。
そうしない場合は、次のようになります。
オペランド変数の前の書き込み操作を検索します。
例:
tempVal
の前の書き込み操作はtempVal=val
です。前の書き込み操作で、逆にトレースするために新しい変数を特定します。
書き込み操作に含まれる変数の上にカーソルを置き、その値を確認します。これらの値は、トレースする変数を判断する際に役立ちます。
例:
tempVal=val
では、val
は全範囲の値を取ることがわかります。したがって、val
をトレースします。新しい変数の前の書き込み操作を検索します。制約を指定するポイントを特定するまでこの方法で逆にトレースを続行します。
例:
val
の前の書き込み操作はval=func()
です。func
の戻り値に対する制約を指定するように選択できます。
変数に応じて、以下のナビゲーション ショートカットを使用し、前のインスタンスを検索します。以下の手順は、Polyspace ユーザー インターフェイスでのみ実行できます。
変数 | 変数の前のインスタンスの検索方法 |
---|---|
ローカル変数 | 次のいずれかの方法を使用してください。
|
グローバル変数 変数を右クリックします。オプション [変数アクセス ビューで表示] が表示される場合、変数はグローバル変数です。 |
|
関数の戻り値
ret=func(); |
|
任意の操作に含まれる変数が前の操作に関連しているかどうかを判断することもできます。コード内の変数間の関係の検出を参照してください。
ヒント
整数オーバーフローと浮動小数点のオーバーフローを区別するには、[結果の詳細] ペインの [詳細] 列を使用します。列ヘッダーをクリックして、整数オーバーフローと浮動小数点のオーバーフローをグループ化します。[詳細] 列が表示されていない場合は、他の列ヘッダーを右クリックして、この列を有効にします。
手順 3: チェックの一般的な原因の検索
オーバーフローの原因となる演算がループ内または再帰関数の本体内で発生する場合、次の手順に従います。
ループの実行または再帰の数を減らすことができるか確認します。
演算のオーバーフローの前で、ループまたは再帰関数内に終了条件を置けるかどうかを確認します。
手順 4: Polyspace の前提条件へのチェックをトレース
コードの前方で発生する Polyspace 前提条件にオレンジ チェックをトレースできるかどうかを確認します。前提条件があてはまらない場合、結果またはコードにコメントまたは正当化情報を追加します。Polyspace ユーザー インターフェイスでのバグ修正または正当化による結果への対処またはPolyspace Access でのバグ修正または正当化による結果への対処 (Polyspace Access)を参照してください。
たとえば、コード内で volatile 変数を使用しているとします。ここで、次のようにします。
Polyspace は、volatile 変数がコード内の各ステップで全範囲であると仮定します。
その変数を使用する演算はオーバーフローする可能性があり、そのため、オレンジになります。
変数が値がより小さな範囲を取るとわかっている場合、コードにコメントおよび正当化情報を追加し、コードを変更しなかった理由を説明します。
詳細については、Code Prover 解析の前提条件を参照してください。
メモ
オレンジ チェックを正当化する前に、コード設計を改善できるかどうかを十分に検討してください。