メインコンテンツ

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

関数ポインターの許容呼び出し (-permissive-function-pointer)

関数ポインターとそれが指す関数の間で型の不一致を許可

説明

このオプションは Code Prover 解析のみに影響します。

検証において、関数ポインターの型が関数の型と一致しない場合でも関数ポインターにより呼び出されるように指定します。

オプションの設定

以下のいずれかの方法を使用してオプションを設定します。

  • Polyspace® ユーザー インターフェイス (デスクトップ製品のみ): プロジェクト構成で [チェック動作] ノードを選択してから、このオプションを選択します。同時に有効にしなければならない他のオプションについては、依存関係を参照してください。

  • Polyspace Platform ユーザー インターフェイス (デスクトップ製品のみ): プロジェクト構成の [静的解析] タブで [実行時エラー][チェック動作] ノードを選択してから、このオプションを選択します。同時に有効にしなければならない他のオプションについては、依存関係を参照してください。

  • コマンド ラインとオプション ファイル: オプション -permissive-function-pointer を使用します。コマンド ライン情報を参照してください。

このオプションを使用する理由

型の不一致が発生している場合、既定では、Code Prover は関数ポインターを介した呼び出しを認識しません。この型の不一致を可能な限り修正します。

次のような場合にこのオプションを使用します。

  • 型の不一致を修正できない。

  • 関数ポインターを介した呼び出しが認識されないため、解析でコードの大部分がカバーされない。

関数ポインターを広範囲に使用するソースでは、このオプションを有効にするとパフォーマンスが低下する可能性があります。こうした低下が起こるのは、検証で検討しなければならない呼び出しグラフが複雑になり、実行パスが増えるからです。まれに、検証でメモリが足りなくなることがあります。

設定

オン

関数ポインターの型が関数の型と一致しない場合でも、検証において関数ポインターによる呼び出しが可能でなければなりません。たとえば、int f(int*) と宣言された関数を、int (*fptr)(void*) と宣言された関数ポインターで呼び出すことができます。

ポインター型の間での型の不一致のみ許容されます。非ポインター型の間での型の不一致はコンパイル エラーになります。たとえば、int f(int) と宣言された関数を、int (*fptr)(double) と宣言された関数ポインターで呼び出すことはできません。

オフ (既定の設定)

検証において、関数ポインターとそれが呼び出す関数の引数と戻り値の型は同一でなければなりません。

型の不一致は、チェック [正確性の条件] で検出されます。

依存関係

このオプションは、[ソース コードの言語] (-lang)[C] に設定されている場合にのみ使用できます。

ヒント

  • このオプションを使用すると、オレンジ チェックの数が増加する可能性があります。これらのオレンジ チェックの一部により、コードの本当の問題が明らかになる場合があります。

    関数ポインター型とそのポイント先となる関数の間で型の不一致が発生している次の例について考えてみます。

    • この例では、関数ポインター obj_fptr の引数は、3 要素配列を指すポインターです。しかし、そのポイント先である関数の対応する引数は、4 要素配列を指すポインターです。foo の本体では、4 つの配列要素が読み取られてインクリメントされます。4 番目の要素は存在せず、++ 演算では無意味な値が読み取られます。

      typedef int array_three_elements[3];
      typedef void (*fptr)(array_three_elements*);
      
      typedef int array_four_elements[4];
      void foo(array_four_elements*);
      
      void main() { 
       array_three_elements arr[3] = {0,0,0};
       array_three_elements *ptr;
       fptr obj_fptr; 
       
       ptr = &arr;
       obj_fptr = &foo;
       
       //Call via function pointer
       obj_fptr(&ptr); 
      }
      
      void foo(array_four_elements* x) {
          int i = 0;
          int *current_pos;
          
          for(i = 0; i< 4; i++) {
            current_pos = (*x) + i;
            (*current_pos)++;
          }
      }

      このオプションを使用しない場合、オレンジの [正確性の条件] チェックが呼び出し obj_fptr(&ptr) において現れ、関数 foo が検証されません。このオプションを使用すると、foo の本体に複数のオレンジ チェックが含まれます。チェックを慎重に確認し、型の不一致による問題が発生していないことを確かめます。

    • この例では、関数ポインターの引数は、3 つの float メンバーをもつ構造体を指すポインターです。しかし、対応する関数の引数は、1 つの配列メンバーをもつ無関係な構造体を指すポインターです。関数本体では、その配列メンバーを仮定して関数 strlen が使用されます。代わりに、strlen 呼び出しで float メンバーを読み取ると、無意味な値 (たとえば、構造体のパディングに格納された値) を読み取る可能性があります。

      #include <string.h>
      struct point {
        float x;
        float y;
        float z;
      };
      struct message {
        char msg[10] ;
      };
      void foo(struct message*);
      
      void main() {
        struct point pt = {3.14, 2048.0, -1.0} ;
        void (*obj_fptr)(struct point *) ;
        
        obj_fptr = &foo; 
        
        //Call via function pointer
        obj_fptr(&pt);
      }
      
      void foo(struct message* x) {
        int y = strlen(x->msg) ;
      }

      このオプションを使用しない場合、オレンジ チェックが呼び出し obj_fptr(&pt) において現れ、関数 foo が検証されません。このオプションを使用すると、関数は strlen 呼び出しにオレンジ チェックを含めます。チェックを慎重に確認し、型の不一致による問題が発生していないことを確かめます。

コマンド ライン情報

パラメーター: -permissive-function-pointer
既定値: オフ
例 (Code Prover): polyspace-code-prover -sources file_name -lang c -permissive-function-pointer
例 (Code Prover Server): polyspace-code-prover-server -sources file_name -lang c -permissive-function-pointer