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

ARR02-C. 初期化子が暗黙的にサイズを定義する場合であっても、配列のサイズは明示的に指定する

ARR02-C. 初期化子が暗黙的にサイズを定義する場合であっても、配列のサイズは明示的に指定する

C 言語規格上、配列変数は、サイズと初期化リテラルの両方を使って宣言してよい。初期化リテラルで指定された要素数からは、配列のサイズが分かる。

初期化リテラルが暗黙的に示す配列サイズは、通常、要素の数で指定される。

int array[] = {1, 2, 3}; /* 3つの要素からなる配列 */

一方、指示子を使って配列要素が連続しない形で初期化することもできる。C 言語規格 [ISO/IEC 9899:2011] のセクション 6.7.9 例 12 には、次のように書かれている。

要素指示子を一つだけ使うことで、配列の両端に初期値を与えることができる。

  int a[MAX] = {
    1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
  };
  

この例において MAX が 10 より大きい場合、配列中央に値 0 の要素が幾つかの存在することになる。MAX が 10 よりも小さい場合、先頭の 5 個の初期化子で与えられた値の幾つかを後半の 5 個の初期化子が上書きする。

C言語規格はまた、初期化子の数と配列の明示的なサイズが異なるときに、どのように配列が初期化されるを定めている。セクション6.7.9の第21および第22パラグラフには次のように書かれている。

集成体型の要素又はメンバの個数より波括弧で囲まれた並びにある初期化子が少ない場合、又は大きさが既知の配列の要素数よりその配列を初期化するための文字列リテラル中の文字数が少ない場合、その集成体型の残りを、静的記憶域期間を持つオブジェクトと同じ規則で暗黙に初期化する。
サイズが決まっていない配列を初期化する場合、配列のサイズは、明示的な初期化子の、最も大きなインデックスで参照される要素によって決定される。初期化子並びの終了時点では、配列型は完全である。

コンパイラは初期化子並びに基づいて配列のサイズを計算することができるが、配列のサイズを明示的に指定しておくことで、冗長ではあるがい、配列サイズが正しいことを確認できる。さらに、配列サイズが初期化子によって示されるサイズより小さい場合に警告を出すこともできる。

このレコメンデーションは、文字列リテラルを使って初期化される文字配列には適用されない点に注意。詳細については「STR11-C. 文字列リテラルで初期化される文字配列のサイズを指定しない」を参照。

違反コード (サイズが正しくない)

以下の違反コード例では、整数配列を初期化しているが、要素の数が多すぎる。

int a[3] = {1, 2, 3, 4};

配列 a のサイズは 3 だが、初期化サイズは 4 である。初期化の最後の要素(4)は無視される。ほとんどのコンパイラはこれをエラーと診断する。

処理系固有の詳細

GCC はこのコードに対して警告を発する。Microsoft Visual Studio は次のようなコンパイルエラーになる。エラー C2078: 初期化子の数が多すぎます.

違反コード (サイズが明示的でない)

この違反コード例では、コンパイラは 4 つの整数からなる配列を割り当てている。配列のサイズは、明示的に指定されていないため、4 に設定される。ただし、初期化子が変わると配列のサイズも変わり、予期せぬ結果を引き起こす。

int a[] = {1, 2, 3, 4};
適合コード

以下の適合コードは、配列範囲を明示的に指定している。

int a[4] = {1, 2, 3, 4};

配列のサイズは、初期化子によって暗黙的に定義されてはいるが、明示的に指定しておくことで、数が一致しない場合にコンパイラやその他の静的分析ツールが診断メッセージを出力することができる。

例外

ARR02-C-EX1: 「STR11-C. 文字列リテラルで初期化される文字配列のサイズを指定しない」は、このレコメンデーションの例外に該当する。このガイドラインは文字列リテラルで初期化される文字配列のサイズを指定しないことを要求する。

リスク評価

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

ARR02-C

P6

L2

自動検出(最新の情報はこちら

ツール

バージョン

チェッカー

説明

Astrée
20.10
array-size-global Partially checked
Axivion Bauhaus Suite

7.2.0

CertC-ARR02 Fully implemented
CodeSonar
6.1p0
LANG.STRUCT.DECL.FAM Declaration of flexible array member
Compass/ROSE




ECLAIR

1.2

CC2.ARR02

Fully implemented

Helix QAC


2021.2

C0678, C0688, C3674, C3684


LDRA tool suite
9.7.1

127 S
397 S
404 S

Fully  implemented

Parasoft C/C++test

2021.1

CERT_C-ARR02-a

Explicitly specify array bounds in array declarations with initializers

PC-lint Plus

1.4

576

Partially supported

Polyspace Bug Finder

R2021a

CERT C: Rec. ARR02-C


Checks for improper array initialization (rec, partially covered).

PRQA QA-C
9.7

0678, 0688, 3674, 3684

Fully implemented
PVS-Studio

7.15

V798
RuleChecker
20.10
array-size-global Partially checked
SonarQube C/C++ Plugin
3.11
S834
関連するガイドライン

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

CERT C CTR02-CPP. Explicitly specify array bounds, even if implicitly defined by an initializer Prior to 2018-01-12: CERT: Unspecified Relationship
CWE 2.11 CWE-665, Incorrect or incomplete initialization Prior to 2018-01-12: CERT:
MISRA C:2012 Rule 8.11 (advisory) Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012 Rule 9.5 (required) Prior to 2018-01-12: CERT: Unspecified Relationship
参考資料
[ISO/IEC 9899:2011] Subclause 6.7.9, "Initialization"
翻訳元

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

ARR02-C. Explicitly specify array bounds, even if implicitly defined by an initializer (revision 83)

Top へ

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