メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

正確性の条件

ポインターのキャストまたは関数ポインターの使用に際して不一致が生じる

説明

このチェックでは、以下が判別されます。

  • ポインター キャストによって配列がより大きい配列にマップされるかどうか

  • 関数ポインターが、有効なプロトタイプを備えた関数を指しているかどうか

  • グローバル変数が、[グローバル アサート] モードから指定された範囲の外にあるかどうかPolyspace 解析のグローバル変数範囲の制約も参照してください。

すべて展開する

typedef int smallArray[10];
typedef int largeArray[100];


void main(void) {
    largeArray myLargeArray;
    smallArray *smallArrayPtr = (smallArray*) &myLargeArray;
    largeArray *largeArrayPtr = (largeArray*) smallArrayPtr;
}

この例では以下のようになります。

  • 最初のポインター キャストでは、largeArray 型のポインターが smallArray 型のポインターにキャストされます。データ型 smallArray は小さい配列を表すため、[正確性の条件] チェックはグリーンになります。

  • 2 番目のポインター キャストでは、smallArray 型のポインターが largeArray 型のポインターにキャストされます。データ型 largeArray はより大きい配列を表すため、[正確性の条件] チェックはレッドになります。

typedef void (*callBack) (float data);
typedef struct
{
    char funcName[20];
    callBack func;
} funcStruct;

funcStruct myFuncStruct;

void main(void)
{
    float val = 0.f;
    myFuncStruct.func = (void*)0;
    myFuncStruct.func(val);
}

この例では、関数ポインター myFuncStruct.func が使用前に NULL を使用して初期化されます。ポインターがデリファレンスされると、[正確性の条件] チェックはレッド エラーを生成します。

typedef void (*callBack) (float data);
typedef struct {
    char funcName[20];
    callBack func;
} funcStruct;

funcStruct myFuncStruct;

void main(void) {
    float val = 0.f;
    myFuncStruct.func(val);
}

この例では、グローバル変数 myFuncStruct は初期化されていないため、関数ポインター myFuncStruct.func には NULL が含まれています。ポインター myFuncStruct.func がデリファレンスされると、[正確性の条件] チェックはレッド エラーを生成します。

#define MAX_MEMSEG 32764
typedef void (*ptrFunc)(int memseg);
ptrFunc operation = (ptrFunc)(0x003c);

void main(void) {
    for (int i=1; i <= MAX_MEMSEG; i++)
        operation(i);
}

この例では、関数ポインター operation がメモリの場所のコンテンツにキャストされています。Polyspace® では、場所に変数か関数のコードが含まれているかどうかや、関数の型指定が十分になされているかどうかは判別できません。したがって、ポインター operation がデリファレンスされており、関数呼び出しで使用されている場合、[正確性の条件] チェックはオレンジとなります。

[正確性の条件] チェックがオレンジであるのは、絶対アドレスの使用が原因の場合、次の変数はそのデータ型で許容される全範囲の値をもつと想定されます。

  • 関数呼び出しからの戻り値を格納する変数。

    次の例では、operation の戻り値が全範囲であると想定されます。

    typedef int (*ptrFunc)(int);
    ptrFunc operation = (ptrFunc)(0x003c);
    
    int main(void) {
      return operation(0);
    }
    

  • 関数の引数によって変更できる変数。

    次の例では、関数ポインター operation は変数 var をポイントするポインター引数 ptr を取ります。operation を呼び出した後、var は全範囲の値をもつと想定されます。

    typedef void (*ptrFunc)(int*);
    ptrFunc operation = (ptrFunc)(0x003c);
    
    void main(void) {
      int var;
      int *ptr=&var;
      operation(ptr);
    }
    

typedef void (*callBack) (float data);

typedef struct {
    char funcName[20];
    callBack func;
} funcStruct;

void g(float data);

funcStruct FctPtrLUT[2] = {
    {"test",g},
    {"test",g}
};

void main(void) {
    float val = 0.f;
    funcStruct* cb;

    cb=FctPtrLUT[0].func;  
    cb->func(val);
}

この例でのコードは、cbfuncStruct へのポインターとして宣言し、main 関数の最後の行で、フィールド func にアクセスする funcStruct へのポインターであるかのように、cb をデリファレンスしています。

しかし実際このコードは、関数 g() のアドレスを指す FctPtrLUT[0].funccb を割り当てています。

想定される cb の型 (funcStruct*) と実際の型 (関数ポインター型 callback) が一致しないため、Polyspace は正しい関数呼び出しを見つけることができず、調査結果にオレンジの [正確性の条件] チェックを割り当てます。この型の不一致により、C++ コードではコンパイル エラーが発生しますが、C コードではコンパイル時にこの型の不一致が検出されないことがあります。

typedef struct {
  double real;
  double imag;
} complex;

typedef int (*typeFuncPtr) (complex*);

int func(int* x);

void main() {
  typeFuncPtr funcPtr = (typeFuncPtr)&func;
  int arg = 0, result = funcPtr((complex*)&arg);
}

この例では、関数ポインター funcPtr は引数タイプが complex* の関数を指します。しかし、このポインターには引数タイプが int* である関数 func のアドレスが割り当てられます。タイプが不一致であるため、[正確性の条件] チェックはオレンジになります。

typedef int (*typeFuncPtr) (int, int);

int func(int);

void main() {
    typeFuncPtr funcPtr = (typeFuncPtr)&func;
    int arg1 = 0, arg2 = 0, result = funcPtr(arg1,arg2);
}

この例では、関数ポインター funcPtr は 2 つの int 引数をもつ関数を指します。しかし、これには、1 つの int 引数のみをもつ関数 func が割り当てられます。引数の数が不一致であるため、[正確性の条件] チェックはオレンジになります。

typedef double (*typeFuncPtr) (int);

int func(int);

void main() {
    typeFuncPtr funcPtr = (typeFuncPtr)&func;
    int arg = 0;
    double result = funcPtr(arg);
}

この例では、関数ポインター funcPtr は戻り値の型が double の関数を指します。しかし、これには、戻り値の型が int の関数 func が割り当てられます。戻り値の型でのこの不一致により、[正確性の条件] チェックはオレンジになります。

int glob = 0;
int func();

void main() {
    glob = 5;
    glob = func();
    glob+= 20;
}

この例では、0..10 の範囲がグローバル変数 glob に対して指定されました。

  • ステートメント glob=5; では、グリーンの [正確性の条件] チェックが glob に対し示されます。

  • ステートメント glob=func(); では、オレンジの [正確性の条件] チェックが glob に対し示されます。スタブ化された関数 func の戻り値が、0..10 の範囲外となる可能性があるからです。

    このステートメントの後、Polyspace では glob0..10 内の値をもつとみなします。

  • ステートメント glob+=20; では、[正確性の条件] のレッド チェックが glob に対し示されますが、これは加算後に、glob20..30 内の値をもつためです。

Polyspace 解析のグローバル変数範囲の制約も参照してください。

チェック情報

グループ: Other
言語: C | C++
頭字語: COR