組み込みソフトウェア・バグの分類学,その傾向と対策 ――ツールを利用してバグ対策の手間を軽減
《バグ・クラス No.3》
NULLポインタ参照
●NULLポインタ参照とは?
NULL値に設定されたポインタをNULL(ヌルまたはナル)ポインタと呼ぶことがあります.多くのC言語の処理系では,NULLは無効なアドレスを示し,stdio.hで次のように定義されています.
#define NULL 0
または,
#define NULL ((void*)0)
このNULLポインタの指し示す領域を参照すると予期しない動作が発生したり,最悪,プログラム・クラッシュを引き起こします.
●NULLポインタ参照の例
簡単な例:
/* アドレス0 に対するポインタを参照しようとしています */
char *p = NULL;
char c;
c = p[0];
●NULLポインタ参照の対策
ポインタを使用する前に,ポインタに代入されているアドレスが有効かどうかを確認しましょう.ここで,ポインタを必ず最初にNULLで初期化するようにしておけば,アドレスが有効かどうかを確認するときNULLが格納されていないかをチェックすることで,危険なメモリ・アクセスを発見しやすくなります.
また,ポインタを介して,参照したものは,最初にその値が満たすべき条件を明確にしておいて,それを満たしているかどうかをチェックするようにしましょう.
●静的解析ツールによるチェック
多くのC言語の実行時の処理系では,アドレスがNULLであるものに対するアクセスをエラーとして扱い,異常終了させます.NULLポインタ参照も,基本的に関数を呼び出した結果の戻り値の影響による実行時の結果として発生する現象なので,正確に検出できるツールは少ないようです.
図4にCodeSonarによる解析例を示します.これはオープン・ソースのfindutilsプログラムを解析し,実行時におけるNULLポインタ参照を検出した例です.
図4 NULLポインタ参照の解析例(Null Pointer Deference Warning)※ 図をクリックすると拡大できます
1809行目のre_acquire_state( )呼び出しはNULLを返す可能性があり,変数stateに対してNULLを設定してしまいます.これが発生した場合,1813行目のstateの参照がNULLポインタ参照となります.また,1810行目を見るとエラー・チェックが行われる間は,NULLが戻されるケースでは,エラー・コードはre_acquire_state( )によって設定されないことが分かります.1890行目でプラス(+)シンボルをクリックすることで,ユーザは,実際にre_acquire_state( )本体の中にドリルダウンし,その実行パスを確認できます.これは表示の関係から,関数の本体をインライン化しています.