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()
の呼出しは実行されない。
|
|
---|---|
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 |
一部実装済み |
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)