チュートリアル : C/C++ コード分析による障害の検出
このチュートリアルでは、C/C++ のコード分析ツールを使って C/C++ コードを分析し、コード障害を検出する方法を示します。
このチュートリアルでは、コード分析を通じて C/C++ コードを分析し、コード障害を検出するプロセスを、順をおって説明します。
このプロセスは、次の手順で構成されます。
ネイティブ コードに対してコード分析を実行する。
コード障害の警告を分析する。
警告をエラーとして扱う。
ソース コードに注釈を付けることにより、コード障害の分析精度を高める。
必須コンポーネント
Visual Studio Premium または Visual Studio Ultimate。
デモのサンプル のコピー。
C/C++ の基本的な理解。
ネイティブ コードに対してコード障害分析を実行するには
Visual Studio で Demo ソリューションを開きます。
これで、Demo ソリューションがソリューション エクスプローラーに読み込まれます。
[ビルド] メニューの [ソリューションのリビルド] をクリックします。
エラーも警告も生成されずに、ソリューションがビルドされます。
ソリューション エクスプローラーで、CodeDefects プロジェクトを選択します。
[プロジェクト] メニューの [プロパティ] をクリックします。
[CodeDefects プロパティ ページ] ダイアログ ボックスが表示されます。
[コード分析] をクリックします。
[ビルド時に C/C++ のコード分析を有効にする] チェック ボックスをオンにします。
CodeDefects プロジェクトを再ビルドします。
コード分析の警告が [エラー一覧] ウィンドウに表示されます。
コード障害の警告を分析するには
[表示] メニューの [エラー一覧] をクリックします。
Visual Studio で開発者が設定しているプロファイルによっては、[表示] メニューの [その他のウィンドウ] をポイントしてから、[エラー一覧] をクリックしなければならない場合もあります。
[エラー一覧] で、次の警告をダブルクリックします。
警告 C6230: 意味の異なる型の間の暗黙的なキャストです: HRESULT をブール値のコンテキストで使用しています
関数 boolProcessDomain() において警告の原因となった行がコード エディターに表示されます。この警告は、ブール型の結果が想定されている 'if' ステートメントで、HRESULT が使用されていることを示しています。
この警告を SUCCEEDED マクロを使って修正します。コードは次のようになります。
if (SUCCEEDED (ReadUserAccount()) )
[エラー一覧] で、次の警告をダブルクリックします。
警告 C6282: 不適切な演算子です: テスト コンテキストで定数に割り当てられています「==」は意図したものですか?
警告された部分を修正し、等価性をテストするようにします。コードは次のようになります。
if ((len == ACCOUNT_DOMAIN_LEN) || (g_userAccount[len] != '\\'))
警告をエラーとして扱うには
警告 C6001 をエラーとして扱うには、Bug.cpp ファイルで、次の #pragma ステートメントをファイルの先頭に追加します。
#pragma warning (error: 6001)
CodeDefects プロジェクトを再ビルドします。
これで、[エラー一覧] に C6001 がエラーとして表示されます。
[エラー一覧] の残りの 2 つの C6001 エラーを修正します。ここでは、i および j を 0 に初期化します。
CodeDefects プロジェクトを再ビルドします。
警告やエラーを出さずにプロジェクトがビルドされます。
ソース コードの注釈によって生成された警告を修正するには (annotation.c)
ソリューション エクスプローラーで、Annotations プロジェクトを選択します。
[プロジェクト] メニューの [プロパティ] をクリックします。
[Annotations プロパティ ページ] ダイアログ ボックスが表示されます。
[コード分析] をクリックします。
[ビルド時に C/C++ のコード分析を有効にする] チェック ボックスをオンにします。
Annotations プロジェクトを再ビルドします。
[エラー一覧] で、次の警告をダブルクリックします。
警告 C6011: NULL ポインター 'newNode' を逆参照しています
この警告は、呼び出し元が戻り値をチェックしなかったことを意味します。この場合、AllocateNode を呼び出すと、NULL 値が返される可能性があります。AllocateNode の関数宣言については、annotations.h のヘッダー ファイルを参照してください。
annotations.cpp ファイルを開きます。
この警告を修正するには、'if' ステートメントを使用して、戻り値をテストするようにします。コードは次のようになります。
if (NULL != newNode)
{
newNode->data = value;
newNode->next = 0;
node->next = newNode;
}
Annotations プロジェクトを再ビルドします。
警告やエラーを出さずにプロジェクトがビルドされます。
ソース コードの注釈を使用するには
次の例のように、Pre 条件と Post 条件を使用して、関数 AddTail の仮パラメーターと戻り値に注釈を付けます。
[returnvalue:SA_Post (Null=SA_Maybe)] LinkedList* AddTail
(
[SA_Pre(Null=SA_Maybe)] LinkedList* node,
int value
)
Annotations プロジェクトを再ビルドします。
[エラー一覧] で、次の警告をダブルクリックします。
警告 C6011: NULL ポインター 'node' を逆参照しています
この警告は、関数に渡されたノードが null の可能性があることを示しており、警告が発生した行番号を示しています。
この警告を修正するには、'if' ステートメントを使用して、戻り値をテストするようにします。コードは次のようになります。
. . . LinkedList *newNode = NULL; if (NULL == node) { return NULL; . . . }
Annotations プロジェクトを再ビルドします。
警告やエラーを出さずにプロジェクトがビルドされます。