演练:对 C/C++ 代码进行缺陷分析

本演练演示如何分析 C/C++ 代码中的潜在代码缺陷。 它使用 C/C++ 代码的代码分析工具。

在此演练中,我们将执行以下操作:

  • 对原生代码运行代码分析。
  • 分析代码缺陷警告。
  • 将警告视为错误。
  • 对源代码进行批注以改进代码缺陷分析。

先决条件

对原生代码运行代码分析

对原生代码运行代码缺陷分析的步骤

  1. 在 Visual Studio 中打开 CppDemo 解决方案。

    CppDemo 解决方案现在将填充解决方案资源管理器。

  2. 在“生成”菜单上,选择“重新生成解决方案”。

    解决方案已生成,未发生任何错误或警告。

  3. 在“解决方案资源管理器”中,选择 CodeDefects 项目

  4. “项目” 菜单上,选择 “属性”

    此时会显示“CodeDefects 属性页”对话框

  5. 选择“代码分析”属性页。

  6. “生成时启用代码分析”属性更改为“是”。 选择“确定”以保存更改 。

  7. 重新生成 CodeDefects 项目。

    代码分析警告在“错误列表”窗口中显示。

  1. 在 Visual Studio 中打开 CppDemo 解决方案。

    CppDemo 解决方案现在将填充解决方案资源管理器。

  2. 在“生成”菜单上,选择“重新生成解决方案”。

    解决方案已生成,未发生任何错误或警告。

    注意

    在 Visual Studio 2017 中,你可能会在 IntelliSense 引擎中看到虚假的警告 E1097 unknown attribute "no_init_all"。 可以放心地忽略此警告。

  3. 在“解决方案资源管理器”中,选择 CodeDefects 项目

  4. “项目” 菜单上,选择 “属性”

    此时会显示“CodeDefects 属性页”对话框

  5. 选择“代码分析”属性页。

  6. 选中“生成时启用代码分析”复选框。 选择“确定”以保存更改 。

  7. 重新生成 CodeDefects 项目。

    代码分析警告在“错误列表”窗口中显示。

分析代码缺陷警告的步骤

  1. 在“视图”菜单上,选择“错误列表” 。

    此菜单项可能不可见。 它取决于你在 Visual Studio 中选择的开发人员配置文件。 你可能需要指向“视图”菜单上的“其他窗口”,然后选择“错误列表”

  2. “错误列表”窗口中,双击以下警告:

    C6230: 语义不同的类型之间的隐式强制转换: 在布尔上下文中使用 HRESULT。

    代码编辑器显示导致函数 bool ProcessDomain() 内出现警告的行。 此警告表明正在应出现布尔值结果的“if”语句中使用 HRESULT。 这通常是一个错误,因为当 S_OK HRESULT 从函数返回时,它表示成功,但在转换为布尔值时,它的计算结果为 false

  3. 使用 SUCCEEDED 宏更正此警告,该宏在 HRESULT 返回值指示成功时转换为 true。 你的代码应与以下代码类似:

    if (SUCCEEDED(ReadUserAccount()))
    
  4. “错误列表”中,双击以下警告:

    C6282: 运算符不正确: 在布尔上下文中执行了常量赋值。 请考虑改用 "=="。

  5. 通过测试相等性来更正此警告。 你的代码应类似于以下代码:

    if ((len == ACCOUNT_DOMAIN_LEN) || (g_userAccount[len] != L'\\'))
    
  6. 通过将 ij 初始化为 0 更正“错误列表”中剩余的 C6001 警告。

  7. 重新生成 CodeDefects 项目。

    项目生成时没有任何警告或错误。

更正源代码注释警告

在 annotation.c 中启用源代码注释警告的步骤

  1. 在解决方案资源管理器中,选择“注释”项目。

  2. “项目” 菜单上,选择 “属性”

    此时会显示“注释属性页”对话框

  3. 选择“代码分析”属性页。

  4. “生成时启用代码分析”属性更改为“是”。 选择“确定”以保存更改 。

  1. 在解决方案资源管理器中,选择“注释”项目。

  2. “项目” 菜单上,选择 “属性”

    此时会显示“注释属性页”对话框

  3. 选择“代码分析”属性页。

  4. 选中“生成时启用代码分析”复选框。 选择“确定”以保存更改 。

在 annotation.c 中更正源代码注释警告的步骤

  1. 重新生成“注释”项目。

  2. 在“生成”菜单上,选择“对注释运行代码分析”。

  3. “错误列表”中,双击以下警告:

    C6011: 取消引用空指针 "newNode"。

    此警告指示调用方未能检查返回值。 在这种情况下,调用 AllocateNode 可能会返回 NULL 值。 有关 AllocateNode 的函数声明,请参阅 annotations.h 头文件。

  4. 游标位于 annotations.cpp 文件中出现警告的位置。

  5. 若要更正此警告,请使用“if”语句测试返回值。 你的代码应与以下代码类似:

    LinkedList* newNode = AllocateNode();
    if (nullptr != newNode)
    {
        newNode->data = value;
        newNode->next = 0;
        node->next = newNode;
    }
    
  6. 重新生成“注释”项目。

    项目生成时没有任何警告或错误。

使用源代码注释发现更多问题

使用源代码注释的步骤

  1. 批注函数 AddTail 的正式参数和返回值,以指示指针值可能为 null:

    _Ret_maybenull_ LinkedList* AddTail(_Maybenull_ LinkedList* node, int value)
    
  2. 在“生成”菜单上,选择“对解决方案运行代码分析”。

  3. “错误列表”中,双击以下警告:

    C6011: 取消引用空指针 "node"。

    此警告指示传入函数中的节点可能为 null。

  4. 若要更正此警告,请使用函数开头的“if”语句测试传入的值。 你的代码应与以下代码类似:

    if (nullptr == node)
    {
         return nullptr;
    }
    
  5. 在“生成”菜单上,选择“对解决方案运行代码分析”。

    现在,项目生成时没有任何警告或错误。

另请参阅

演练:对托管代码进行代码缺陷分析
C/C++ 代码分析