チュートリアル : C/C++ コード分析による障害の検出
このチュートリアルでは、C/C++ コードを分析して潜在的なコードの障害を見つける方法について説明します。 C/C++ コードのコード分析ツールを使用します。
このチュートリアルでは、次の作業を行います。
- ネイティブ コードでコード分析を実行します。
- コードの障害の警告を分析します。
- 警告をエラーとして扱います。
- コード障害分析を向上させるためにソース コードに注釈を付けます。
前提条件
- CppDemo サンプルのコピー。
- C/C++ の基本的な理解。
ネイティブ コードでコード分析を実行する
ネイティブ コードでコード障害分析を実行するには
Visual Studio で CppDemo ソリューションを開きます。
これで、CppDemo ソリューションがソリューション エクスプローラーに読み込まれます。
[ビルド] メニューの [ソリューションのリビルド] をクリックします。
ソリューションは、エラーや警告なしでビルドされます。
ソリューション エクスプローラーで、CodeDefects プロジェクトを選択します。
[プロジェクト] メニューの [プロパティ] をクリックします。
[CodeDefects プロパティ ページ] ダイアログ ボックスが表示されます。
[コード分析] プロパティ ページを選択します。
[ビルドに対するコード分析の有効化] プロパティを [はい] に変更します。 [OK] を選択して変更を保存します。
CodeDefects プロジェクトをリビルドします。
コード分析の警告が [エラー一覧] ウィンドウに一覧表示されます。
Visual Studio で CppDemo ソリューションを開きます。
これで、CppDemo ソリューションがソリューション エクスプローラーに読み込まれます。
[ビルド] メニューの [ソリューションのリビルド] をクリックします。
ソリューションは、エラーや警告なしでビルドされます。
Note
Visual Studio 2017 では、IntelliSense エンジンで誤った警告
E1097 unknown attribute "no_init_all"
が表示されることがあります。 この警告は無視しても問題ありません。ソリューション エクスプローラーで、CodeDefects プロジェクトを選択します。
[プロジェクト] メニューの [プロパティ] をクリックします。
[CodeDefects プロパティ ページ] ダイアログ ボックスが表示されます。
[コード分析] プロパティ ページを選択します。
[ビルドに対するコード分析の有効化] チェック ボックスをオンにします。 [OK] を選択して変更を保存します。
CodeDefects プロジェクトをリビルドします。
コード分析の警告が [エラー一覧] ウィンドウに一覧表示されます。
コードの障害の警告を分析するには
[表示] メニューの [エラー一覧] を選択します。
このメニュー項目は、表示されない場合があります。 それは、Visual Studio で選択した開発者プロファイルによって決まります。 [表示] メニューの [その他のウィンドウ] をポイントし、[エラー一覧] を選択しなければならない場合があります。
[エラー一覧] ウィンドウで、次の警告をダブルクリックします。
C6230: 意味の異なる型の間の暗黙的なキャストです: HRESULT をブール値のコンテキストで使用しています。
コード エディターには、関数
bool ProcessDomain()
内で警告が発生した行が表示されます。 この警告は、HRESULT
ブール値の結果が予想される 'if' ステートメントで使用されていることを示します。S_OK
の HRESULT が関数から返された場合は成功を示しますが、ブール値に変換するとfalse
に評価されるため、これは通常は間違いです。この警告を修正するには、
SUCCEEDED
マクロを使用します。これは、HRESULT
の戻り値が成功を示している場合にtrue
に変換します。 コードは、次のようなものになります。if (SUCCEEDED(ReadUserAccount()))
[エラー一覧] で、次の警告をダブルクリックします。
C6282: 不適切な演算子です: ブール値のコンテキストの定数の代入式です。 代わりに、'==' を使用してください。
この警告を修正するには、等価性をテストします。 コードは、次のコードのようになります。
if ((len == ACCOUNT_DOMAIN_LEN) || (g_userAccount[len] != L'\\'))
[エラー一覧] にある残りの C6001 警告を修正するには、
i
とj
を 0 に初期化します。CodeDefects プロジェクトをリビルドします。
プロジェクトが、警告やエラーが発生することなくビルドされます。
ソース コードの注釈の警告を修正する
annotation.c でソース コード注釈の警告を有効にするには
ソリューション エクスプローラーで、Annotations プロジェクトを選択します。
[プロジェクト] メニューの [プロパティ] をクリックします。
[Annotations プロパティ ページ] ダイアログ ボックスが表示されます。
[コード分析] プロパティ ページを選択します。
[ビルドに対するコード分析の有効化] プロパティを [はい] に変更します。 [OK] を選択して変更を保存します。
ソリューション エクスプローラーで、Annotations プロジェクトを選択します。
[プロジェクト] メニューの [プロパティ] をクリックします。
[Annotations プロパティ ページ] ダイアログ ボックスが表示されます。
[コード分析] プロパティ ページを選択します。
[ビルドに対するコード分析の有効化] チェック ボックスをオンにします。 [OK] を選択して変更を保存します。
annotation.c でソース コード注釈の警告を修正するには
Annotations プロジェクトをリビルドします。
[ビルド] メニューの [Annotations でコード分析を実行] を選択します。
[エラー一覧] で、次の警告をダブルクリックします。
C6011: NULL ポインター 'newNode' を逆参照しています。
この警告は、呼び出し元が戻り値を確認する際のエラーを示しています。 この場合、
AllocateNode
の呼び出しは NULL 値を返す場合があります。AllocateNode
の関数の宣言については、annotations.h ヘッダー ファイルをご覧ください。カーソルは、警告が発生した annotations.cpp ファイル内の場所にあります。
この警告を修正するには、'if' ステートメントを使用して戻り値をテストします。 コードは、次のようなものになります。
LinkedList* newNode = AllocateNode(); if (nullptr != newNode) { newNode->data = value; newNode->next = 0; node->next = newNode; }
Annotations プロジェクトをリビルドします。
プロジェクトが、警告やエラーが発生することなくビルドされます。
ソース コード注釈を使用して、より多くの問題を検出する
ソース コード注釈を使用するには
関数
AddTail
の仮パラメーターと戻り値に注釈を付け、ポインターの値が null になる可能性があることを示します。_Ret_maybenull_ LinkedList* AddTail(_Maybenull_ LinkedList* node, int value)
[ビルド] メニューの [ソリューションでコード分析を実行] をクリックします。
[エラー一覧] で、次の警告をダブルクリックします。
C6011: NULL ポインター 'node' を逆参照しています。
この警告は、関数に渡されるノードが null になる可能性があることを示します。
この警告を修正するには、関数の先頭で 'if' ステートメントを使用して、渡された入力値をテストします。 コードは、次のようなものになります。
if (nullptr == node) { return nullptr; }
[ビルド] メニューの [ソリューションでコード分析を実行] をクリックします。
これで、プロジェクトが警告やエラーが発生することなくビルドされます。