メインコンテンツ

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

CERT C: Rule DCL40-C

Do not create incompatible declarations of the same function or object

説明

ルール定義

同じ関数またはオブジェクトについて互換性のない宣言を作成しないようにします。1

Polyspace 実装

ルール チェッカーは、"宣言の不一致" をチェックします。

すべて展開する

問題

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

リスク

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

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

修正方法

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

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

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

例 - 2 つのファイル内の宣言の不一致

file1.c

int foo(void) { //Noncompliant
    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 "square.h" 
#include "circle.h" 
struct aCircle circle; 
struct aSquare square;

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

test2.c

#include "circle.h" 
#include "square.h" 
struct aCircle circle; 
struct aSquare square; //Noncompliant

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

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 が推定するため、宣言不一致の欠陥が square.hsquare で報告されます。このエラーは 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 "square.h" 
#include "circle.h" 
struct aCircle circle; 
struct aSquare square;

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

test2.c

#include "circle.h" 
#include "square.h" 
struct aCircle circle; 
struct aSquare square;

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

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. 解析を再実行。

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

チェック情報

グループ: Rule 02.宣言と初期化 (DCL)

バージョン履歴

R2019a で導入

すべて展開する


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.