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

DCL19-C. 変数と関数の有効範囲を最小限にする

変数および関数の有効範囲は、識別子に対するすべての参照が可能な最小限の範囲で宣言すべきである。

必要以上に広い有効範囲を使用すると、コードの可読性が落ち、保守が困難になる。また、意図せぬ変数を参照してしまう可能性がある(「DCL01-C. サブスコープで変数名を再利用しない」を参照)。

違反コード

以下のコード例では、関数 counter() がグローバル変数 count をインクリメントし、この変数が最大値を超えた時点でただちに復帰する。

unsigned int count = 0;

void counter() {
  if (count++ > MAX_COUNT) return;
  /* ... */

}

変数 count がこの関数だけからアクセスされることを前提にすると、count が可能な最小限の有効範囲内で定義されていないため、この例は違反している。

適合コード

以下の適合コードでは、変数 countcounter() 関数の有効範囲内で静的変数として宣言している。この静的な修飾子は、ローカル変数(関数内部にある変数)に適用されたとき、変数の生存期間(持続期間)を修飾する。これにより、生存期間はプログラムが持続する限り持続する。つまり、現在、呼び出されている関数が次回に呼び出されるまでは消滅しない。

void counter() {
  static unsigned int count = 0;
  if (count++ > MAX_COUNT) return;
  /* ... */

}

キーワード static は、変数の再初期化も防止する。

違反コード

カウンタ変数 ifor ループの外で宣言されているが、これはこのレコメンデーションに違反している。なぜなら、変数を使用するブロックの中で宣言していないからである。このコードが他のインデックス変数 j と一緒に再利用され、さらに変数 i が既に宣言されている場合、ループは間違った変数をカウンタとして繰り返す可能性がある。

size_t i = 0;

for (i=0; i < 10; i++){
  /* 操作を実行する */
}
適合コード

このレコメンデーションに適合するには、使用する場所で変数を宣言し、コードの可読性と再利用性を改善することである。この例では、ループインデックス変数 ifor ループのなかで宣言することになる。この要件は、C 標準で仕様が緩和され、可能になったものである。

for (size_t i=0; i < 10; i++) {
  /* 操作を実行する */
}
違反コード (関数宣言)

以下のコード例では、関数 f() は、同じ翻訳単位で定義された関数 g() 内部からのみ呼び出されている。デフォルトでは、関数宣言は extern であり、これらの関数はグローバルシンボルテーブルに配置され、他の翻訳単位から使用できる。

int f(int i) {
  /* 関数定義 */
}

int g(int i) {
  int j = f(i);
  /* ... */
} 
適合コード

この適合コードでは、f() は、外部として宣言されている。このため、関数宣言の有効範囲が現在の翻訳単位に限定され、関数が外部のシンボルテーブルに含まれなくなる。これにより、グローバル名前空間での混乱が抑制され、関数が偶然または意図的に別の翻訳単位から呼び出されることがなくなる。

static int f(int i) {
  /* 関数定義 */
}

int g(int i) {
  int j = f(i);
  /* ... */
} 
リスク評価

有効範囲を最小限にし損ねると、信頼性が低く、可読性も低く、再利用性も低いコードになる。

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

DCL19-C

P2

L3

自動検出

ツール

バージョン

チェッカー

説明

ECLAIR

1.1

filscope

実装済み

関連するガイドライン
CERT C++ Secure Coding Standard DCL07-CPP. Minimize the scope of variables and methods
翻訳元

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

DCL19-C. Minimize the scope of variables and functions (revision 34)

Top へ

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