メインコンテンツ

宣言の不一致

関数または変数の宣言の間の不一致

説明

このチェッカーは、既定の Polyspace® as You Code 解析では非アクティブにされますPolyspace as You Code 解析で非アクティブにされるチェッカー (Polyspace Access)を参照してください

この欠陥は、関数または変数の宣言が、関数または変数の他のインスタンスと一致しない場合に発生します。

リスク

異なるコンパイル ユニット内の 2 つの変数宣言の間で不一致が発生する場合、標準的なリンカーはアルゴリズムに従って、その変数に対していずれかの宣言を選択します。リンカーが選択するものとは異なる変数宣言を想定している場合、その変数を使用するときに予期しない結果になる可能性があります。

同様の問題は、関数宣言の不一致により発生することもあります。

修正方法

修正方法は宣言の不一致のタイプによって異なります。どちらの宣言も実際には同じオブジェクトのことを指している場合は、同じ宣言を使用します。それらの宣言が異なるオブジェクトのことを指している場合は、いずれかの変数の名前を変更します。変数名を変更する場合、必ずその変数を使用しているすべての場所で変更してください。

宣言が以前のプリプロセッサ命令の影響を受けているため、宣言の不一致が発生する可能性があります。たとえば、マクロ内で宣言が行われ、あるインクルード パスではそのマクロが定義され、別のインクルード パスでは未定義であることがあります。このような宣言の不一致はデバッグするのが困難な場合があります。2 つのインクルード パス間の相違を特定し、競合するマクロ定義を修正します。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

すべて展開する

file1.c

int foo(void) {
    return 1;
}

file2.c

double foo(void);

int bar(void) {
    return (int)foo();
}

この例では、file1.c は integer を foo() の戻り値として宣言します。file2.c では、double を foo() の戻り値として宣言しています。この不一致はコンパイル エラーを引き起こす可能性があります。Polyspace は、file2 内の foo の 2 番目のインスタンスでの欠陥を報告します。

修正 — 関数の戻り値を揃える

1 つの修正方法として、関数の宣言を互いが一致するように変更することができます。この例では、file2.c における foo の宣言を file1.c と一致するように変更することで、欠陥を修正できます。

file1.c

int foo(void) {
    return 1;
}

file2.c

int foo(void);

int bar(void) {
    return foo();
}

test1.c

#include<stdio.h>
#include "square.h" 
#include "circle.h" 
struct aCircle circle; 
struct aSquare square;

void func2();

int main(){ 
    square.side=1; 
    circle.radius=1;
    
    func2();
    return 0;
}

test2.c

#include<stdio.h>
#include "circle.h" 
#include "square.h" 
struct aCircle circle; 
struct aSquare square;

void func2(){ 
    printf("%d\n", square.side); 
    printf("%d\n", circle.radius);
}

circle.h

#pragma pack(1)

extern struct aCircle{ 
    int radius; 
} circle; 

square.h

extern struct aSquare { 
    unsigned int side:1; 
} square;

この例では、square.hsquare のアライメントが test2.csquare と異なると Polyspace が推定するため、宣言不一致の欠陥が test2.csquare で報告されます。このエラーは circle.h#pragma pack(1) ステートメントが特定のアライメントを宣言しているため発生します。test2.c では、circle.hsquare.h の前にインクルードされています。したがって、circle.h からの #pragma pack(1) ステートメントは構造体 aCircle の後で既定のアライメントにリセットされません。この省略のため、test2.c は構造体 aSquare square1 バイトのアライメントをもつと推測します。この欠陥はコンパイル エラーを引き起こす可能性があります。

修正 — パッキング ステートメントを閉じる

1 つの修正方法として、aCircle struct 宣言後に構造体の割り当てをリセットすることができます。GNU® または Microsoft® Visual コンパイラは #pragma pack() ステートメントを circle.h の最後に追加して欠陥を修正します。

test1.c

#include<stdio.h>
#include "square.h" 
#include "circle.h" 
struct aCircle circle; 
struct aSquare square;

void func2();

int main(){ 
    square.side=1; 
    circle.radius=1;

    func2();
    return 0;
}

test2.c

#include<stdio.h>
#include "circle.h" 
#include "square.h" 
struct aCircle circle; 
struct aSquare square;

void func2(){ 
    printf("%d\n", square.side); 
    printf("%d\n", circle.radius);
}

circle.h

#pragma pack(1)

extern struct aCircle{ 
    int radius; 
} circle; 

#pragma pack()

square.h

extern struct aSquare { 
    unsigned int side:1; 
} square;

その他のコンパイラは異なる #pragma pack 構文を必要とします。構文については、ご使用のコンパイラのドキュメントを参照ください。

修正 — [Ignore pragma pack directives] オプションを使用

1 つの修正方法として、[Ignore pragma pack directives] オプションを Bug Finder 解析に追加することができます。[宣言の不一致] の欠陥を起こさずに、構造体の割り当てを構造体ごとに変更するには、この修正を使用します。

  1. [構成] ペインで [詳細設定] ペインを指定します。

  2. [その他] ボックスで -ignore-pragma-pack を入力します。

  3. 解析を再実行。

    [宣言の不一致] の欠陥は解決されています。

結果情報

グループ: プログラミング
言語: C | C++
既定値: オン
コマンド ライン構文: DECL_MISMATCH
影響度: High

バージョン履歴

R2013b で導入

すべて展開する