組み込みソフトウェア・バグの分類学,その傾向と対策 ――ツールを利用してバグ対策の手間を軽減
《バグ・クラス No.4》
未初期化変数
●未初期化変数とは?
C言語のauto変数は,値を明確に設定しないかぎり,その値は不定となります.そのため,これを参照した結果について実行時の動作は保証されず,不具合を引き起こす可能性があります.
●未初期化変数の例
簡単な例:
/* 初期化されていない変数の値を使用している */
int j;
printf("%d\n", j);
●未初期化変数の対策
auto変数は,宣言時または使用する直前に初期化しましょう.
また,変数を初期化する場所とそれを使用する場所が離れてしまうと,その変数が初期化されているかどうか,その値が何なのかなどをレビューの際に確認しづらくなってしまいます.
●静的解析ツールによるチェック
コンパイラの中には,そのコンパイル・オプションを指定すると,値が不定のまま参照される可能性のあるauto変数をチェックできるものがあります.また,コーディング・ルール・チェッカなどでもこれをチェックできます.ただし,どちらも関数間にまたがるような複雑な処理については,未初期化ワーニングの誤検出を起こす可能性があります.実際には変数に有効な値が割り当られているのにもかからず,そこまでの振る舞いを解析できないことがあるのです.
図5にCodeSonarによる解析例を示します.これは米国の連邦食品医薬品局(FDA:Food and Drug Administration)がある医療機器メーカのコードをCodeSonarに入力し,解析を行った結果の一部です.
図5 未初期化変数の解析例(Uninitialized Variable Warning)※ 図をクリックすると拡大できます
ここでは,関数の振る舞いや分岐のつながりを正確に追った結果として,未初期化変数ワーニングを出力しています.
関数S_Keyでは,いくつかのローカル変数が定義されています.ここで,変数is_button_pressed,number,button_pressは,関数の最初にデフォルト値で初期化されます.しかし,変数buttonは初期化されていません.
ただしそれは,1267行目で呼び出される関数ProcessButton( )で,引き数として渡され,そこで値を割り当てられる可能性もある,と推測することもできます.さらに,関数ProcessButton( )は条件付きループ内から呼び出され,ProcessButtonn( )内でも条件付きの命令を含むであろうと判断されます.そして,そこでは変数buttonに対して有効な値が割り当てられない可能性もあります.そのため,1272行目のswitch命令でbuttonが使用された場合,そこが「未初期化変数」ワーニングとして出力されます.switch命令に従って実行されると,思いがけないパス実行を引き起こす可能性があります.そしてそれは,最終的に装置の故障を引き起こすかもしれません.