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

DCL41-C. switch 文のなかでは最初の case 句より前で変数宣言しない

C 標準、6.8.4.2節、第4パラグラフには次のような規定がある[ISO/IEC 9899:2011]。

switch 文は、制御式の値、スイッチ本体(switch body)と呼ばれる文の中の default ラベルの有無及び case ラベルの値に依存して、スイッチ本体、スイッチ本体の中の文又はスイッチ本体の次の文に制御を移す。

最初の case 文より前に変数の宣言と初期化を行い、case 文の内側でそれを使おうとした場合、変数の有効範囲は switch ブロックの内側になるが初期化が行われず、結果として変数の値は不定なままとなる。

違反コード

次の違反コード例では、switch 文の内側の最初の case ラベルより前に変数を宣言し実行文を記述している。

#include <stdio.h>

extern void f(int i);

void func(int expr) {
  switch (expr) {
    int i = 4;
    f(i);
  case 0:
    i = 17;
    /* default ラベルのコードに実行が移る */
  default:
    printf("%d\n", i);
  }
}
処理系固有の詳細

先のコードを GCC 4.8.1 で実行した場合、変数 i は switch ブロック内で自動記憶域期間をもつように実体化されるが、初期化はされない。そのため、制御式 expr の値が 0 でない場合、printf() の呼出しは i の不定の値にアクセスすることになる。同様に、f() の呼出しは実行されない。

expr の値

出力

0

17

ゼロでない

不定

適合コード

以下の適合コードでは、最初の case 句よりも前にあった文は、switch 文の前に記述されている。

#include <stdio.h>

extern void f(int i);

int func(int expr) {
  /*
   * switch ブロックの外にコードを移動
   * これにより文は実行される
   */
  int i = 4;
  f(i);

  switch (expr) {
    case 0:
      i = 17;
      /* default ラベルのコードに実行が移る */
    default:
      printf("%d\n", i);
  }
  return 0;
}
リスク評価

switch ブロックの最初の case 文より前で条件式の使用や変数の初期化を行うと、プログラムの 予期せぬ動作未定義の動作を引き起こす可能性がある。

ルール

深刻度

可能性

修正コスト

優先度

レベル

DCL41-C

P4

L3

自動検出

ツール

バージョン

チェッカー

説明

Astrée 18.10

switch-skipped-code

Fully checked
Axivion Bauhaus Suite 6.9.0 CertC-DCL41 実装済み
Clang 3.9 -Wsometimes-uninitialized
Coverity 2017.07

MISRA C 2004 Rule 15.0

MISRA C 2012 Rule 16.1

実装済み
LDRA tool suite  9.7.1 385 S 実装済み
Parasoft C/C++test
10.4.1
CERT_C-DCL41-a

A switch statement shall only contain switch labels and switch clauses, and no other code

Polyspace Bug Finder

R2018a

MISRA C:2012 Rule 16.1

All switch statements shall be well-formed

PRQA QA-C
9.5

3234
2008
2882

一部実装済み

PVS-Studio

6.23

V622
RuleChecker
18.10

switch-skipped-code

実装済み
関連するガイドライン

(テーブルの説明)

Taxonomy

Taxonomy item

Relationship

MISRA C:2012 Rule 16.1 (required) Prior to 2018-01-12: CERT: Unspecified Relationship
参考情報
[ISO/IEC 9899:2011] 6.8.4.2, "The switch Statement"
翻訳元

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

DCL41-C. Do not declare variables inside a switch statement before the first case label (revision 81)

Top へ

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