AUTOSAR C++14 Rule M5-0-16
A pointer operand and any pointer resulting from pointer arithmetic using that operand shall both address elements of the same array
R2021a 以降
説明
ルール定義
A pointer operand and any pointer resulting from pointer arithmetic using that operand shall both address elements of the same array.
根拠
配列要素へのポインターを使用するポインター算術演算の結果が次のいずれも指していない場合、動作は未定義になります。
配列の要素。
配列の最後の要素を超えた位置。次に例を示します。
int arr[3]; int* res; res = arr+3; // res points to one beyond arr
ルールは次の演算に適用されます。ptr は配列要素へのポインターで、int_exp は整数式です。
ptr+int_expint_exp+ptrptr-int_expptr+ +++
ptr--
ptrptr--ptr[int_exp]
Polyspace 実装
配列の一部ではない単一のオブジェクトは、1 要素の配列と見なされます。たとえば、このコード例では
arr_oneは 1 要素の配列と等価です。Polyspace® はポインターptr_to_oneのインクリメントにフラグを設定しません。arr_oneの最後の要素を超えた位置を指しているからです。void f_incr(int* x){ int* ptr_to_one = x; ++ptr_to_one; // Compliant } void func(){ int arr_one=1; // Equivalent to array of one element f_incr(&arr_one); }Polyspace は、ポインターが配列を指している場合、ポインター算術演算でのポインター パラメーターの使用にフラグを設定しません。たとえば、このコード スニペットで
f1に配列を渡した場合、f1の&a1[2]はルールに準拠しています。void f1( int* const a1){ int* b= &a1[2]; // Compliant } void f2(){ int arr[3] {}; f1(arr); }複数の要素を含む構造体で、要素に対するポインターが構造体に割り当てられたメモリ内を指していたり、構造体の最後の要素を超えた位置を指していたりする場合、Polyspace は、別の要素を指すポインターとなる要素のポインターに対する算術演算の結果にフラグを設定しません。
たとえばこのコード スニペットでは、
ptr_to_structへの代入はルールに準拠しています。myStruct.elem1の外部を指していますが、それでもmyStructの内部にとどまっているからです。最終結果としてのアドレスが構造体に割り当てられたメモリの内部であったとしても、要素の次元より大きいインデックスを使用して要素の内容にアクセスすることはルールに準拠していません。void func(){ struct { char elem1[10]; char elem2[10]; } myStruct; char* ptr_to_struct = &myStruct.elem1[11]; //Compliant // Address of myStruct.elem1[11] is inside myStruct char val_to_struct = myStruct.elem1[11]; // Non-compliant }多次元配列では、Polyspace は、部分配列の要素へのアクセスに部分配列の次元より大きいインデックスを使用している箇所にフラグを設定します。Polyspace は、アドレスがトップレベルの配列に割り当てられたメモリの内部である場合、同じ部分配列のアドレスの代入にはフラグを設定しません。
たとえばこのコード スニペットでは、ポインター
ptr_to_arrへの代入はルールに準拠しています。このポインターはmulti_arrに割り当てられたメモリの内部のアドレスを指しているからです。変数arr_valへの代入はルールに準拠していません。部分配列要素へのアクセスに使用されるインデックス (3) が部分配列の次元 (2) よりも大きいからです。void func(){ int multi_arr[5][2]; // Assigned memory is inside top level array int* ptr_to_arr = &multi_arr[2][3]; //Compliant // Use of index 3 with subarray of size 2 int arr_val = multi_arr[2][3]; // Non-compliant }Polyspace は、ポインターが配列の最後の要素を超えた位置を指す場合、そのポインターのデリファレンスにフラグを設定します。たとえばこのコード スニペットでは、
ptrの代入はルールに準拠していますが、ptrのデリファレンスは準拠していません。tab+3は tab の最後の要素を超えた位置です。void derefPtr(){ int tab[3] {}; int* ptr = tab+3; //Compliant int res = *(tab+3); // Non-compliant }ポインター算術演算の結果が
nullptrになる場合、Polyspace はこのチェッカーを起動しません。たとえば、次のコードを考えます。void g(int *p); void add(int* p, int n) { g(p + n); //Compliant } void foo() { add(nullptr, 0); }add()でのポインター演算の結果はnullptrになります。Polyspace は、この演算にフラグを設定しません。
チェッカーの拡張
入力値が不明であり、入力のサブセットのみがエラーの原因として考えられる場合、既定の Bug Finder 解析ではこのルールに対する違反が報告されない場合があります。特定のシステム入力値を原因とする違反の有無をチェックするには、より厳密な Bug Finder 解析を実行してください。特定のシステム入力値から欠陥を見つけるための Bug Finder チェッカーの拡張を参照してください。
トラブルシューティング
ルール違反が想定されるものの、Polyspace から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。
例
チェック情報
| グループ: 式 |
| カテゴリ: Required、Automated |