Polyspace 解析の外的制約
Polyspace® は指定されたコードを使用して、変数の範囲やポインターに許容されるバッファー サイズなどの項目について仮定を行います。Polyspace が行う仮定は予想よりも幅広くなる場合があり、その結果、Bug Finder で誤検知が発生する場合や、Code Prover のオレンジ チェックが増加する場合があります。このような誤検知やオレンジ チェックを減らすために、以下に対する外的制約を指定できます。
グローバル変数。
ユーザー定義関数。
スタブ関数。
詳細については、Polyspace 解析の外的制約の指定を参照してください。制限の部分的なリストについては、制約指定の制限を参照してください。
外的制約の効果
以下の関数について考えます。
int getFlooredNumber(int total, int size) {
return total/size;
}size は不明であるため、この関数の解析を行うと、次のようになります。
Polyspace Code Prover™ では、[ゼロ除算] オレンジ チェックが表示されます。オレンジ チェックは、Code Prover がゼロ除算エラーの可能性があると見なしていることを示しますが、このエラーはすべての実行パスで発生するわけではありません。
Polyspace Bug Finder™ では、オプション
[システムのすべての入力値を考慮する、さらに厳密なチェックを実行] (-checks-using-system-input-values)を使用すると、[整数のゼロ除算] 欠陥と、この欠陥を引き起こした可能性のある 1 つの入力値 (この場合ではsizeの 0) が表示されます。より複雑な例 (条件内部で除算が発生する場合など) では、このオプションを使用しなくても、不明な入力からの欠陥が表示されます。
いずれの場合でも、解析において、そのデータ型から入力変数 size が取り得る値が判別されます。変数 size のデータ型は int であるため、int のサイズが 32 ビットであるターゲットでは、この変数の値の範囲は [-231, 231-1] であると想定されます。
ある入力の値が特定の範囲に限定されることが分かっている場合は、入力に外的制約 (データ範囲指定 (DRS) とも呼ばれる) を指定できます。たとえば上記の例では、size にゼロを含まない範囲を指定すると、以下のようになります。
Code Prover で [ゼロ除算] オレンジ チェックが表示されなくなります。
Bug Finder で [整数のゼロ除算] 欠陥が表示されなくなります。
コードの外部に存在する設計制約をエミュレートするために、外的制約を指定することができます。たとえば、入力変数が車両速度のような物理量を表す場合、変数値を車両に設計されている速度に制約することができます。
制約指定
Polyspace デスクトップ製品のユーザー インターフェイスで、[制約指定] ウィンドウを介して制約を指定できます。制約は、他のプロジェクトで再利用できる XML ファイルに保存されます。

次の表は、[制約指定] ウィンドウのさまざまな列について説明しています。制約 XML ファイルを直接編集して制約を指定する場合 (たとえば、Polyspace サーバー製品の場合) のために、この表では、ユーザー インターフェイスの列と XML ファイルのエントリの間の対応も示しています。太字で強調表示されている XML エントリは、[制約指定] ウィンドウの対応する列に表示されます。
| 列 | 設定 | XML ファイル エントリ |
|---|---|---|
| 名前 | プロジェクト内で、データ範囲を指定できる変数と関数の一覧が表示されます。 この列には、以下の展開可能なメニュー項目が 3 つ表示されます。
|
<function name = "funcName" ...>
<scalar name = "arg1" ...>
<pointer name = "arg2" ...> |
| ファイル | 変数または関数を格納しているソース ファイルの名前が表示されます。 | <file name = "C:\Project1\Sources\file.c" ...> |
| 属性 | 変数または関数に関する情報が表示されます。 たとえば、静的変数の場合には | <function name="funcName" attributes="unused" ...> |
| データ型 | 変数の型が表示されます。 | <scalar name="arg1" complete_type="int32" ...> |
| main ジェネレーターによる呼び出し | ユーザー定義関数にのみ該当します。 main ジェネレーターがこの関数を呼び出すかどうかを以下のように指定します。
| <function name="funcName" main_generator_called="MAIN_GENERATOR" ...> |
| 初期化モード | ソフトウェアが変数にどのように範囲を割り当てるかを指定します。
ユーザー定義関数は スタブ関数は C の検証では、グローバル ポインターは
| <scalar name="arg1" init_mode="INIT" ...> |
| 初期化範囲 | 変数の最小値と最大値を指定します。
16 進数値を使うこともできます。たとえば、 変数 変数 enum week{ sunday, monday=0, tuesday, wednesday, thursday, friday, saturday}; | <scalar name="arg1" init_range="-1..0"...> |
| ポインターの初期化 | ポインターにのみ該当します。初期化モードで ポインターが NULL になるかどうかを指定します。
メモ C++ プロジェクトには該当しません。制約指定の制限を参照してください。 | <pointer name="arg1" initialize_pointer="Not NULL"...> |
| 初期化の割り当て | ポインターにのみ該当します。初期化モードで 参照されているオブジェクトをどのように割り当てるかを指定します。
スタブ関数のポインター引数には他の 2 つのオプションを使用できます。
スタブ関数では、オプション メモ C++ プロジェクトには該当しません。制約指定の制限を参照してください。 | <pointer name="arg1" init_pointed="MAIN_GENERATOR"...> |
| 割り当て可能オブジェクト数 | ポインターにのみ該当します。 ポインターによって参照されるオブジェクトの個数を指定します (参照される各オブジェクトは 1 つの配列と見なされます)。 [初期化の割り当て] パラメーターは、割り当てられたオブジェクトが実際に初期化される個数を指定します。たとえば、次のコードを考えます。 void func(int *ptr) {
assert(ptr[0]==1);
assert(ptr[1]==1);
}
どちらのアサーションもグリーンです。以下の制約を指定するとします。
2 番目のアサーションはオレンジになります。 ファイル サイズが不明な非常に大きな配列内の任意の場所をポインターで指すことができることを指定するには、キーワード "max " を使用します。解析結果を見ると、そのポインターのオフセットとバッファーのサイズが非常に大きくなっていることが分かります。オフセットとバッファーのサイズは、使用するターゲット プロセッサ タイプのポインター サイズやその他の特性によって異なります。Polyspace がこの方法を使用して作成する最大のオブジェクトは、2^27-1 バイト (134217726 バイト) のバッファーです。 メモ C++ プロジェクトには該当しません。制約指定の制限を参照してください。 | <pointer name="arg1" number_allocated="10"...> |
| グローバル アサート | グローバル初期化のとき、および各割り当ての後に、変数にアサート チェックを実行するかどうかを指定します。 | <scalar name="glob" global_assert="YES"...> |
| グローバル アサート範囲 | チェックする範囲の最小値と最大値を指定します。 | <scalar name="glob" assert_range="0..200"...> |
| コメント | DRS 値の理由など、入力の説明です。 | <scalar name="glob" comment="Speed Range"...> |
制約指定の制限
次のタイプの制約は、制約指定インターフェイスを使用して指定することはできません。これらの制限の一部は、回避するために独自のスタブと main() を定義できます。詳細は、手動スタブと手動の main() 関数を使用した Polyspace 解析の変数範囲の制約を参照してください。
制約指定インターフェイスでは、次の制約はサポートされていません。
C++ では、関数のポインター引数または参照引数を制約することはできません。
多態性により、C++ のポインターまたは参照はクラス階層内の複数のクラスのオブジェクトを指す可能性があり、異なるコンストラクターを呼び出すことが必要になる場合があります。制約指定の予備解析で、制約するオブジェクト タイプや呼び出すコンストラクターを判別することはできません。
関数の戻り値をその入力に関連付ける制約は指定できません。制約には一定の範囲のみを指定できます。
制約には複数の範囲を指定できません。たとえば、関数引数が値 -1 か、範囲 [1,100] の値のどちらかをもつように指定することはできません。代わりに、範囲 [-1,100] を指定するか、もしくは値 -1 を 1 回、範囲 [1,100] を 1 回指定して、2 回の別々の分析を実行します。
1 つの共用体に属する異なるフィールドに別々の制約を指定することはできません。
複数レベルの間接参照でアクセスされるオブジェクトを制約することはできません。たとえば、ポインターには制約を指定できますが、ポインターへのポインターには制約を指定できません。