変数の初期化漏れを防ぐ
| 設計内容分類 | 組み込みソフトウェアにおけるC言語記述 |
|---|
実現したい仕様・課題
変数は初期化されていない状態では値が不定(スタック上に残った過去の値)となり、そのまま参照されると期待しない動作となります。未初期化の不具合は「たまたま動く」ことがあるため再現性が低く、実機でのみ発生する原因究明の難しい不具合になりがちです。初期化漏れを仕組みとして予防したいというのが課題です。
設計のポイント
初期化漏れを予防するために、まず「複数の変数を同時に宣言しない」ことを推奨します。int i, j, k = 0; と書くと、初期化されるのはkだけで、iとjは不定のままです。1行1変数で int i = 0; int j = 0; int k = 0; と書けば、初期化の有無が一目で確認でき、レビューでの見落としも防げます。配列の初期化は、int a[256] = {0}; の初期化子指定、または memset(a, 0x00, sizeof(a)); で行います({0}指定は全要素が0で初期化されます)。構造体も同様に = {0} で全メンバをゼロ初期化できます。なお、static変数やグローバル変数はスタートアップルーチンでゼロ初期化されるのがC言語の仕様ですが、初期値に意味がある変数は宣言時に明示的に初期値を書き、コードだけで意図が読み取れるようにしておくことを推奨します。あわせて、コンパイラの警告機能(未初期化変数の使用警告)を有効にし、警告ゼロを保つ運用にすると、初期化漏れの多くはコンパイル段階で検出できます。ポインタ変数は特に危険で、未初期化ポインタへのアクセスは暴走に直結するため、宣言時にNULLを代入し、使用前にNULL判定を行う習慣を徹底します。
【コード例】
// △ 複数同時宣言:kのみ初期化され、iとjは不定
int i, j, k = 0;
// ○ 1行1変数で確実に初期化
int i = 0;
int j = 0;
int k = 0;
// 配列・構造体の初期化
int a[256] = {0};
memset(a, 0x00, sizeof(a));
SETTING s = {0}; // 構造体の全メンバをゼロ初期化
補足情報
設計のポイント 一覧
組み込みソフトウェアにおけるC言語記述のポイント
- リングバッファで受信データを取りこぼさない
- switch-caseによるステートマシンの実装
- 割り込みハンドラは短く書く
- constを活用する(ROM配置と書き換え防止)
- ビット演算によるレジスタ・フラグ操作
- 固定幅整数型(stdint.h)を使う
- volatile修飾子を正しく使う
- 構造体の宣言にpackedを指定する
- ソースコードのエンディアン変換
- sizeofを使用する
- 特殊文字の記述にエスケープ文字を使用する
- 変数の初期化漏れを防ぐ
- 外部バスの使用
- sprintf関数を使う
- 列挙型(enum)を使う
- 構造体を使う
- 標準関数を使う
- 条件演算子を使う
- インクリメント演算子を使う
- C言語記述の際はアプリ層とドライバ層に分ける



