ウォークスルー 1:__KLOCWORK__ マクロを使用した NPD 誤検知の処理
__KLOCWORK__ マクロの典型的な用途は、カスタムアサートにより発生した NPD 誤検知の処理です。
アサート
アサートは有効性チェック、および関数の事前条件と事後条件を実装するために、C/C++ コードで広く使用されています。たとえば、関数が非 NULL ポインターの引数を予期する場合は、次のようなコードを使用します。
1 void my_function(my_data_t *ptr) 2 { 3 MY_ASSERT(ptr != NULL); 4 char *name = ptr->name; 5 }
静的解析ツールがコード内のアサートを認識し、条件チェックとして適切に処理することが重要になります。たとえば、上のコード例の MY_ASSERT が "NULL のチェック ptr" として認識されない場合、Klocwork により 4 行目で NULL ポインター逆参照の指摘が報告されます (誤検知)。
標準 C/C++ ライブラリでは、assert.h に assert() のデフォルト実装が提供されていますが (通常、条件をチェックし、エラーの場合に停止するマクロ)、次の目的のためにカスタム ASSERT マクロを定義することが一般的です。
- 診断の向上 - 通常標準バージョンはエラーが発生した条件、ファイル名、および行番号を表示しますが、カスタムアサートでは、エラーメッセージに関数またはモジュール名を追加したり、一部のロギングシステムからファイルにエラーを報告することができます。
- ビルド構成の柔軟性を向上 - 製品のデバッグバージョンでは、アサートを定義して拡張エラーレポートを実装するか、デバッガーを自動的に起動できますが、アサートのリリースバージョンでは、空のステートメントに拡張して追加健全性チェックのオーバーヘッドを排除できます。
__KLOCWORK__ マクロの使用
条件に応じてコンパイルしたコードをソースに追加する手段は、異なる環境に対応するために一般的に使用されています。Klocwork コンパイラによって常に定義される __KLOCWORK__ マクロを使用すると、Klocwork の実行中のみに特定のコードが有効になり、それ以外の場合はコードが無視されます。__KLOCWORK__ ブロックにアサートタイプのマクロの別の定義を追加する場合は、コードを変更する必要がなく、管理がシンプルになります。
たとえば、次のコードがあるとします。
1 MY_ASSERT(a!=NULL); 2 use(a->mm);
Klocwork が不正に生産定義 MY_ASSERT を処理して、abort 条件を理解しないと、誤ってポジティブな NPD を行 2 に報告する可能性があります。Klocwork により簡単で、より標準的なカスタムアセットの定義を送ることで、これが発生する確率を下げることができます。
1 #ifdef __KLOCWORK__ 2 # define MY_ASSERT(x) do { if (!(x)) abort(); } while (0) 3 #else 4 # define MY_ASSERT(x) ... production, advanced definition of assert ... 5 #endif