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

本演练演示如何通过使用 C/C++ 代码分析工具来分析 C/C++ 代码以查找潜在的代码缺陷。

在本演练中,逐步完成使用代码分析来分析 C/C++ 代码以查找潜在代码缺陷的过程。

您将完成下列步骤:

  • 在本机节点上运行代码分析。

  • 分析代码缺陷警告。

  • 将警告视为错误。

  • 批注源代码以改进代码缺陷分析。

系统必备

  • Visual Studio 高级专业版 或 Visual Studio 旗舰版。

  • 演示示例 的副本。

  • 对 C/C++ 进行基本了解。

对本机代码运行代码缺陷分析

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

    演示解决方案现在将出现在**“解决方案资源管理器”**中。

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

    将生成解决方案,并且不出现任何警告或错误。

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

  4. 在**“项目”菜单上,单击“属性”**。

    将显示**“CodeDefects 属性页”**对话框。

  5. 单击**“代码分析”**。

  6. 单击**“生成时启用 C/C++ 代码分析”**复选框。

  7. 重新生成 CodeDefects 项目。

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

分析代码缺陷警告

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

    根据您在 Visual Studio 中选择的开发人员配置文件,可能需要指向**“视图”菜单上的“其他窗口”,然后单击“错误列表”**。

  2. 在**“错误列表”**中双击下列警告:

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

    代码编辑器显示导致在函数 boolProcessDomain() 中出现警告的代码行。该警告指示“if”语句中正在使用 HRESULT,而原本应使用布尔值结果。

  3. 通过使用 SUCCEEDED 宏来更正该警告。您的代码应与以下代码类似:

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

    警告 C6282:运算符不正确: 在测试上下文中执行了常数赋值。Was == intended?(事实是否确实像预计的那样?)

  5. 通过测试是否等同来更正该警告。代码看起来应类似下面这样:

    if ((len == ACCOUNT_DOMAIN_LEN) || (g_userAccount[len] != '\\'))
    

将警告视为错误

  1. 在 Bug.cpp 文件中,将下面的 #pragma 语句添加到文件的开头,将警告 C6001 视为错误:

    #pragma warning (error: 6001)
    
  2. 重新生成 CodeDefects 项目。

    在**“错误列表”**中,C6001 现在显示为一个错误。

  3. 通过将 i 和 j 初始化为 0,更正**“错误列表”**中的其余两个 C6001 错误。

  4. 重新生成 CodeDefects 项目。

    将生成项目,并且不出现任何警告或错误。

更正 annotation.c 中的源代码批注警告

  1. 在解决方案资源管理器中,选择 Annotations 项目。

  2. 在**“项目”菜单上,单击“属性”**。

    将显示**“Annotations 属性页”**对话框。

  3. 单击**“代码分析”**。

  4. 选中**“生成时启用 C/C++ 代码分析”**复选框。

  5. 重新生成 Annotations 项目。

  6. 在**“错误列表”**中双击下列警告:

    警告 C6011:正在取消 NULL 指针“newNode”的引用。

    该警告指示调用方检查返回值失败。在这种情况下,调用 AllocateNode 可能会返回一个 NULL 值(有关 AllocateNode 的函数声明,请参见 annotations.h 头文件)。

  7. 打开 annotations.cpp 文件。

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

    if (NULL != newNode)

    {

    newNode->data = value;

    newNode->next = 0;

    node->next = newNode;

    }

  9. 重新生成 Annotations 项目。

    将生成项目,并且不出现任何警告或错误。

使用源代码批注

  1. 通过使用 Pre 和 Post 条件,批注函数 AddTail 的形参和返回值,如下面的示例所示:

    [returnvalue:SA_Post (Null=SA_Maybe)] LinkedList* AddTail

    (

        [SA_Pre(Null=SA_Maybe)] LinkedList* node,

        int value

     )

  2. 重新生成 Annotations 项目。

  3. 在**“错误列表”**中双击下列警告:

    警告 C6011:正在取消 NULL 指针“node”的引用。

    此警告指出传递到函数的节点可能为 null,同时还指出诱发警告的行号。

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

      . . .
      LinkedList *newNode = NULL; 
      if (NULL == node)
      {
           return NULL;
          . . .
      }
    
  5. 重新生成 Annotations 项目。

    将生成项目,并且不出现任何警告或错误。

请参见

任务

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