演练:对 C/C++ 代码进行缺陷分析
本演练演示如何分析 C/C++ 代码中的潜在代码缺陷。 它使用 C/C++ 代码的代码分析工具。
在此演练中,我们将执行以下操作:
- 对原生代码运行代码分析。
- 分析代码缺陷警告。
- 将警告视为错误。
- 对源代码进行批注以改进代码缺陷分析。
先决条件
- CppDemo 示例的副本。
- 对 C/C++ 有一个基本的了解。
对原生代码运行代码分析
对原生代码运行代码缺陷分析的步骤
在 Visual Studio 中打开 CppDemo 解决方案。
CppDemo 解决方案现在将填充解决方案资源管理器。
在“生成”菜单上,选择“重新生成解决方案”。
解决方案已生成,未发生任何错误或警告。
在“解决方案资源管理器”中,选择 CodeDefects 项目。
在 “项目” 菜单上,选择 “属性” 。
此时会显示“CodeDefects 属性页”对话框。
选择“代码分析”属性页。
将“生成时启用代码分析”属性更改为“是”。 选择“确定”以保存更改 。
重新生成 CodeDefects 项目。
代码分析警告在“错误列表”窗口中显示。
在 Visual Studio 中打开 CppDemo 解决方案。
CppDemo 解决方案现在将填充解决方案资源管理器。
在“生成”菜单上,选择“重新生成解决方案”。
解决方案已生成,未发生任何错误或警告。
注意
在 Visual Studio 2017 中,你可能会在 IntelliSense 引擎中看到虚假的警告
E1097 unknown attribute "no_init_all"
。 可以放心地忽略此警告。在“解决方案资源管理器”中,选择 CodeDefects 项目。
在 “项目” 菜单上,选择 “属性” 。
此时会显示“CodeDefects 属性页”对话框。
选择“代码分析”属性页。
选中“生成时启用代码分析”复选框。 选择“确定”以保存更改 。
重新生成 CodeDefects 项目。
代码分析警告在“错误列表”窗口中显示。
分析代码缺陷警告的步骤
在“视图”菜单上,选择“错误列表” 。
此菜单项可能不可见。 它取决于你在 Visual Studio 中选择的开发人员配置文件。 你可能需要指向“视图”菜单上的“其他窗口”,然后选择“错误列表”。
在“错误列表”窗口中,双击以下警告:
C6230: 语义不同的类型之间的隐式强制转换: 在布尔上下文中使用 HRESULT。
代码编辑器显示导致函数
bool ProcessDomain()
内出现警告的行。 此警告表明正在应出现布尔值结果的“if”语句中使用HRESULT
。 这通常是一个错误,因为当S_OK
HRESULT 从函数返回时,它表示成功,但在转换为布尔值时,它的计算结果为false
。使用
SUCCEEDED
宏更正此警告,该宏在HRESULT
返回值指示成功时转换为true
。 你的代码应与以下代码类似:if (SUCCEEDED(ReadUserAccount()))
在“错误列表”中,双击以下警告:
C6282: 运算符不正确: 在布尔上下文中执行了常量赋值。 请考虑改用 "=="。
通过测试相等性来更正此警告。 你的代码应类似于以下代码:
if ((len == ACCOUNT_DOMAIN_LEN) || (g_userAccount[len] != L'\\'))
通过将
i
和j
初始化为 0 更正“错误列表”中剩余的 C6001 警告。重新生成 CodeDefects 项目。
项目生成时没有任何警告或错误。
更正源代码注释警告
在 annotation.c 中启用源代码注释警告的步骤
在解决方案资源管理器中,选择“注释”项目。
在 “项目” 菜单上,选择 “属性” 。
此时会显示“注释属性页”对话框。
选择“代码分析”属性页。
将“生成时启用代码分析”属性更改为“是”。 选择“确定”以保存更改 。
在解决方案资源管理器中,选择“注释”项目。
在 “项目” 菜单上,选择 “属性” 。
此时会显示“注释属性页”对话框。
选择“代码分析”属性页。
选中“生成时启用代码分析”复选框。 选择“确定”以保存更改 。
在 annotation.c 中更正源代码注释警告的步骤
重新生成“注释”项目。
在“生成”菜单上,选择“对注释运行代码分析”。
在“错误列表”中,双击以下警告:
C6011: 取消引用空指针 "newNode"。
此警告指示调用方未能检查返回值。 在这种情况下,调用
AllocateNode
可能会返回 NULL 值。 有关AllocateNode
的函数声明,请参阅 annotations.h 头文件。游标位于 annotations.cpp 文件中出现警告的位置。
若要更正此警告,请使用“if”语句测试返回值。 你的代码应与以下代码类似:
LinkedList* newNode = AllocateNode(); if (nullptr != newNode) { newNode->data = value; newNode->next = 0; node->next = newNode; }
重新生成“注释”项目。
项目生成时没有任何警告或错误。
使用源代码注释发现更多问题
使用源代码注释的步骤
批注函数
AddTail
的正式参数和返回值,以指示指针值可能为 null:_Ret_maybenull_ LinkedList* AddTail(_Maybenull_ LinkedList* node, int value)
在“生成”菜单上,选择“对解决方案运行代码分析”。
在“错误列表”中,双击以下警告:
C6011: 取消引用空指针 "node"。
此警告指示传入函数中的节点可能为 null。
若要更正此警告,请使用函数开头的“if”语句测试传入的值。 你的代码应与以下代码类似:
if (nullptr == node) { return nullptr; }
在“生成”菜单上,选择“对解决方案运行代码分析”。
现在,项目生成时没有任何警告或错误。