JPCERT コーディネーションセンター

DCL36-C. 矛盾する結合の種類を使用して識別子を宣言しない

異なるスコープで宣言された識別子や同一スコープ内で複数回宣言された識別子からオブジェクトや関数への参照を結合(linkage)と呼ぶ。結合には、外部結合内部結合無結合の3種類がある。これらは次のような特徴を持つ[Kirch-Prinz 2002]。

C 標準 [ISO/IEC 9899:2011] において、結合は次のように定義されている。

オブジェクトまたは関数に対するファイルスコープの識別子の宣言が記憶域クラス指定子 static を含む場合その識別子は、内部結合を持つ。

識別子が、その識別子の以前の宣言が可視であるスコープにおいて、記憶域クラス指定子 extern を伴って宣言される場合、次のとおりとする。以前の宣言において内部結合または外部結合が指定されているならば、新しい宣言における識別子は以前の宣言と同じ結合を持つ。可視である以前の宣言がない場合、または以前の宣言が無結合である場合、この識別子は外部結合を持つ。

関数の識別子の宣言が記憶域クラス指定子を持たない場合、その結合は、記憶域クラス指定子 extern を伴って宣言された場合と同じ規則で決定する。オブジェクトの識別子の宣言がファイルスコープをもち、かつ記憶域クラス指定子を持たない場合、その識別子の結合は、外部結合とする。

オブジェクトまたは関数以外を宣言する識別子、関数仮引数を宣言する識別子、および記憶域クラス指定子 extern を伴わないブロックスコープのオブジェクトを宣言する識別子は、無結合とする。

(1つの翻訳単位内で)内部結合および外部結合の両方に分類される識別子を使用すると、未定義の動作となる。(「undefined behavior 8」も参照。)翻訳単位には、ソースファイルとそのヘッダ、そして前処理指令 #include によってインクルードされるすべてのソースファイルが含まれる。

以下の表は、単一の翻訳単位内で 2 回宣言されるオブジェクトに割り当てられる結合を示す。列は最初の宣言を、行は2回めの宣言を表す。

1 回目 / 2 回目

static

なし

extern

static

内部

未定義

内部

なし

未定義

なし

外部

extern

未定義

未定義

外部

違反コード

以下のコード例では、i2i5 は内部結合および外部結合の両方を持つように定義されている。どちらの識別子を使用する場合も、未定義の動作となる。

int i1 = 10;        /* 定義、外部結合 */
static int i2 = 20; /* 定義、内部結合 */
extern int i3 = 30; /* 定義、外部結合 */
int i4;             /* 仮定義、外部結合 */
static int i5;      /* 仮定義、内部結合 */

int i1;  /* 正しい仮定義 */
int i2;  /* 未定義、前の定義と結合の不一致 */
int i3;  /* 正しい仮定義 */
int i4;  /* 正しい仮定義 */
int i5;  /* 未定義、前の定義と結合の不一致 */

int main(void) {
  /* ... */
  return 0;
}
処理系固有の詳細

Microsoft Visual Studio 2013 でコンパイルすると、最も厳しい診断レベルを指定していても、このコード例に対して警告を出さない。

GCC コンパイラは、i2i5 の矛盾する定義に対し、致命的エラーを出す。

適合コード

以下の適合コードには矛盾する定義は含まれていない。

int i1 = 10;        /* 定義、外部結合 */
static int i2 = 20; /* 定義、内部結合 */
extern int i3 = 30; /* 定義、外部結合 */
int i4;             /* 仮定義、外部結合 */
static int i5;      /* 仮定義、内部結合 */

int main(void) {
  /* ... */
  return 0;
}
リスク評価

内部結合および外部結合の両方に分類される識別子の使用は、未定義の動作となる。

ルール

深刻度

可能性

修正コスト

優先度

レベル

DCL36-C

P8

L2

自動検出

ツール

バージョン

チェッカー

説明

Astrée
19.04

static-function-declaration

static-object-declaration

Partially checked
Axivion Bauhaus Suite

6.9.0

CertC-DCL36 Fully implemented
Coverity
2017.07
PW.LINKAGE_CONFLICT 実装済み

ECLAIR

1.2

CC2.DCL36

実装済み

GCC
4.3.5



Klocwork
2018

MISRA.FUNC.STATIC.REDECL


LDRA tool suite
9.7.1

461 S, 575 S, 2 X

実装済み

Splint
3.1.1



Parasoft C/C++test
10.4.1
CERT_C-DCL36-a Identifiers shall not simultaneously have both internal and external linkage in the same translation unit
Polyspace Bug Finder

R2018a

MISRA C:2012 Rule 8.2

MISRA C:2012 Rule 8.4

MISRA C:2012 Rule 8.8

MISRA C:2012 Rule 17.3

Function types shall be in prototype form with named parameters

A compatible declaration shall be visible when an object or function with external linkage is defined

The static storage class specifier shall be used in all declarations of objects and functions that have internal linkage

A function shall not be declared implicitly

PRQA QA-C
9.5
0625 (U) 実装済み
RuleChecker
19.04

static-function-declaration

static-object-declaration
一部実装済み
関連するガイドライン

(テーブルの説明)

Taxonomy

Taxonomy item

Relationship

MISRA C:2012 Rule 8.2 (required) Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012 Rule 8.4 (required) Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012 Rule 8.8 (required) Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012 Rule 17.3 (mandatory) Prior to 2018-01-12: CERT: Unspecified Relationship
参考資料
[Banahan 2003] Section 8.2, "Declarations, Definitions and Accessibility"
[ISO/IEC 9899:2011] 6.2.2, "Linkages of Identifiers"
[Kirch-Prinz 2002]
翻訳元

これは以下のページを翻訳したものです。

DCL36-C. Do not declare an identifier with conflicting linkage classifications (revision 128)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter