メインコンテンツ

MISRA C:2023 Rule 8.5

An external object or function shall be declared once in one and only one file

R2024a 以降

説明

ルール定義

An external object or function shall be declared once in one and only one file 1 .

根拠

ヘッダー ファイル内で識別子を宣言すると、その識別子が定義または使用される任意の翻訳単位にそのヘッダー ファイルをインクルードできます。ヘッダー ファイル内で宣言をモジュール化すると、以下の整合性を維持するうえで役立ちます。

  • 宣言と定義。

  • 異なる翻訳単位での宣言。

このルールは、ヘッダー ファイル内で外部オブジェクトまたは関数を宣言する手法を強制します。

Polyspace 実装

ルール チェッカーでは、明示的および暗黙的な extern 宣言をチェックします (仮定義は無視されます)。チェッカーは、次の変数または関数にフラグを設定します。

  • ヘッダー ファイル以外で extern と宣言されている

  • 複数回宣言されている (たとえば、ヘッダー ファイルで 1 回、ヘッダー ファイル以外で 1 回宣言されているなど)。

このチェッカーは以下のように動作します。

  • pragma weak__attribute__((weak)) など、コンパイラに固有の移植可能でない方法による関数宣言のオーバーライドを無視する。

  • コードで使用されていない typedef と関数宣言を無視する。

  • 再宣言をルール違反と見なす。たとえば、コードで weak シンボルを宣言してから、後でその記号を再宣言すると、Polyspace® は違反を報告します。このような違反を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

トラブルシューティング

ルール違反を想定していてもその違反が表示されない場合、コーディング規約違反が想定どおりに表示されない理由の診断を参照します。

すべて展開する

この例では、外部関数 func2() の宣言がヘッダー ファイル以外で行われているため、この宣言は非準拠です。他の外部オブジェクトと関数の宣言はヘッダー ファイル内で行われているため、このルールに準拠しています。この問題を修正するには、ヘッダー ファイル内で func2() を宣言します。

ヘッダー ファイル:


/* header.h */
extern int var;
extern void func1(void);   /* Compliant */

ソース ファイル:


/* module.c */
#include "header.h"

extern void func2(void);   /* Noncompliant */

/* Definitions */
int var = 0;
void func1(void) {}

この例では、関数 func()header1.h で宣言されています。この関数は header2.h 内で呼び出されます。module2.c にはファイル header2.h が含まれていますが、おそらく誤りにより、header1.h が含まれていません。module2.c には func() の呼び出しが含まれますが、その宣言は含まれていないことから、コンパイラはコンパイル時に関数の暗黙的な宣言を生成します。ファイル module1.c に含まれる header1.h には、明示的な宣言が含まれています。同じ外部関数に対して明示的な宣言と暗黙的な宣言を行うことは、このルールに準拠していません。Polyspace は違反を報告します。Polyspace は欠陥を報告します。[結果の詳細] セクションでPolyspace は以下のものにフラグを設定します。

  • header1.h での明示的な宣言。

  • 暗黙的な宣言の作成をトリガーする module2.c での関数呼び出し。

//header1.h
extern void func(void);
//header2.h

#define __STATIC_INLINE static inline

__STATIC_INLINE void Reset(void)
{
	//...
	func(); //Noncompliant
}
//module1.c
#include "header2.h"
#include "header1.h"

void foo(void)
{
}

//module2.c
#include "header2.h"

void bar(void)
{
}

この違反を修正するには、ファイル header1.hmodule2.c に含めます。

この例では、関数 func() の宣言がヘッダー header.h に含まれています。ソース ファイル module1.c および module2.cfunc() の呼び出しが含まれていますが、ヘッダー ファイルがこれらのソース ファイルに含まれていません。これは手違いの可能性があります。その結果、コンパイラは func() の 2 つの暗黙的な宣言を作成し、このルールに対する違反となります。Polyspace はこの違反を報告します。[結果の詳細] セクションでPolyspace は暗黙的な宣言の作成をトリガーする関数呼び出しにフラグを設定します。

//header.h

extern void func(void);
 
//module1.c

void foo(void)
{
	func(); //Noncompliant
}

//module2.c

void bar(void)
{
	func(); 
}

この違反を修正するには、ファイル header.hmodule1.cmodule2.c に含めます。

チェック情報

グループ: 宣言と定義
カテゴリ: 必要
AGC カテゴリ: 推奨

バージョン履歴

R2024a で導入


1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.

The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:

  • MISRA C:2004

  • MISRA C:2012

  • MISRA C:2023

  • MISRA C++:2008

  • MISRA C++:2023

MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.