使用 C++ Core Guidelines 检查器

C++ Core Guidelines 是由 C++ 专家和设计师创建的一组关于 C++ 编码的可移植指南、规则和最佳做法。 Visual Studio 目前支持将这些规则的子集作为其 C++ 代码分析工具的一部分。 核心准则检查器默认安装在 Visual Studio 2017 和 Visual Studio 2019 中。 它们作为 Visual Studio 2015 的 NuGet 包提供

C++ Core Guidelines 项目

C++ Core Guidelines 由 Bjarne Stroustrup 等人创建,是一份安全有效地使用新式 C++ 的指南。 这些准则强调了静态类型安全和资源安全。 它们确定了消除或最大程度地减少语言中最容易出错的部分的方法。 它们还建议如何使代码更简单、更可靠并具有更好的性能。 这些准则由标准 C++ 基金会维护。 有关详细信息,请参阅文档 C++ Core Guidelines,以及访问 GitHub 上的 C++ Core Guidelines 文档项目文件。

在 Code Analysis 中启用 C++ Core Check 准则

C++ Core Check 规则的子集包含在 Microsoft 本机建议规则集中。 它是启用代码分析时默认运行的规则集。

在项目上启用代码分析

  1. 打开项目的“属性页”对话框

  2. 选择“配置属性”>“Code Analysis”属性页。

  3. 选中“生成时启用 Code Analysis”复选框。

Property page for Code Analysis General settings.

若要启用更多 Core Check 规则,请打开下拉列表,然后选择要包括的规则集:

Dropdown for additional C++ Core Check rule sets.

C++ Core Check 规则的子集包含在 Microsoft 本机建议规则集中。 它是启用 Microsoft 代码分析时默认运行的规则集。

要在项目上启用代码分析,请执行以下操作:

  1. 打开项目的“属性页”对话框

  2. 选择“配置属性”>“Code Analysis”属性页。

  3. 设置“生成时启用 Code Analysis”和“启用 Microsoft Code Analysis”属性。

还可以选择运行所有受支持的 C++ Core Check 规则,或选择运行你自己的子集:

启用更多 Core Check 规则

  1. 打开项目的“属性页”对话框

  2. 选择“配置属性”>“Code Analysis”>“Microsoft”属性页。

  3. 打开“活动规则”下拉列表,然后选择“选择多个规则集”。

  4. 在“添加或删除规则集”对话框中,选择要包括的规则集

示例

下面是 C++ Core Check 规则可以发现的一些问题的示例:

// CoreCheckExample.cpp
// Add CppCoreCheck package and enable code analysis in build for warnings.

int main()
{
    int arr[10];           // warning C26494
    int* p = arr;          // warning C26485

    [[gsl::suppress(bounds.1)]] // This attribute suppresses Bounds rule #1
    {
        int* q = p + 1;    // warning C26481 (suppressed)
        p = q++;           // warning C26481 (suppressed)
    }

    return 0;
}

此示例演示了 C++ Core Check 规则可以发现的一些警告:

  • C26494 是规则 Type.5:始终初始化对象。

  • C26485 是规则 Bounds.3:无数组到指针的衰减。

  • C26481 是规则 Bounds.1:不要使用指针算术。 请改用 span

安装并启用 C++ Core Check 代码分析规则集,然后编译此代码。 代码分析输出前两个警告,并取消第三个警告。 下面是 Visual Studio 2015 中示例代码的生成输出:

1>------ Build started: Project: CoreCheckExample, Configuration: Debug Win32 ------
1>  CoreCheckExample.cpp
1>  CoreCheckExample.vcxproj -> C:\Users\username\documents\visual studio 2015\Projects\CoreCheckExample\Debug\CoreCheckExample.exe
1>  CoreCheckExample.vcxproj -> C:\Users\username\documents\visual studio 2015\Projects\CoreCheckExample\Debug\CoreCheckExample.pdb (Full PDB)
c:\users\username\documents\visual studio 2015\projects\corecheckexample\corecheckexample\corecheckexample.cpp(6): warning C26494: Variable 'arr' is uninitialized. Always initialize an object. (type.5: http://go.microsoft.com/fwlink/p/?LinkID=620421)
c:\users\username\documents\visual studio 2015\projects\corecheckexample\corecheckexample\corecheckexample.cpp(7): warning C26485: Expression 'arr': No array to pointer decay. (bounds.3: http://go.microsoft.com/fwlink/p/?LinkID=620415)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

C++ Core Guidelines 可帮助你编写更好、更安全的代码。 但是,你可能会发现不应该应用规则或配置文件的实例。 很容易直接在代码中取消它。 可以使用 [[gsl::suppress]] 属性来阻止 C++ Core Check 检测和报告以下代码块中的任何违反规则的行为。 可以标记单个语句以取消特定规则。 甚至可以通过写入 [[gsl::suppress(bounds)]] 而不包括特定规则编号来禁止整个边界配置文件。

支持的规则集

随着新规则被添加到 C++ Core Guidelines 检查器中,为预先存在的代码生成的警告数量可能会增加。 可以使用预定义的规则集来筛选要启用的规则类型。 可在 Visual Studio C++ Core Check 参考下找到大多数规则的参考文章。

15.3 这些规则首次出现在 Visual Studio 2017 版本 15.3 中
15.5 这些规则首次出现在 Visual Studio 2017 版本 15.5 中
15.6 这些规则首次出现在 Visual Studio 2017 版本 15.6 中
15.7 这些规则首次出现在 Visual Studio 2017 版本 15.7 中
16.0 这些规则首次出现在 Visual Studio 2019 版本 16.0 中
16.3 这些规则首次出现在 Visual Studio 2019 版本 16.3 中

可以选择将警告限制为一个或多个组。 “本机最小”和“本机建议”规则集包括 C++ Core Check 规则和其他 PREfast 检查。

若要查看可用的规则集,请打开“项目属性”对话框。 在“属性页”对话框中,选择“配置属性”>“Code Analysis”>“常规”属性页。 然后,在“规则集”组合框中打开下拉列表以查看可用的规则集。 若要生成规则集的自定义组合,请选择“选择多个规则集”。 “添加或删除规则集”对话框列出了可从中选择的规则。 有关在 Visual Studio 中使用规则集的详细信息,请参阅使用规则集指定要运行的 C++ 规则

若要查看可用的规则集,请打开“项目属性”对话框。 在“属性页”对话框中,选择“配置属性”>“Code Analysis”>“Microsoft”属性页。 然后,在“活动规则”组合框中打开下拉列表以查看可用的规则集。 若要生成规则集的自定义组合,请选择“选择多个规则集”。 “添加或删除规则集”对话框列出了可从中选择的规则。 有关在 Visual Studio 中使用规则集的详细信息,请参阅使用规则集指定要运行的 C++ 规则

C++ Core Guidelines 检查器附带有一个头文件,该文件定义了各种宏,可用于更轻松地在代码中禁止显示整个类别的警告:

ALL_CPPCORECHECK_WARNINGS
CPPCORECHECK_TYPE_WARNINGS
CPPCORECHECK_RAW_POINTER_WARNINGS
CPPCORECHECK_CONST_WARNINGS
CPPCORECHECK_OWNER_POINTER_WARNINGS
CPPCORECHECK_UNIQUE_POINTER_WARNINGS
CPPCORECHECK_BOUNDS_WARNINGS

这些宏对应于规则集,并展开为以空格分隔的警告编号列表。 通过使用适当的 pragma 构造,可以配置对项目或代码段感兴趣的有效规则集。 在以下示例中,代码分析仅警告缺少常量修饰符:

#include <CppCoreCheck\Warnings.h>
#pragma warning(disable: ALL_CPPCORECHECK_WARNINGS)
#pragma warning(default: CPPCORECHECK_CONST_WARNINGS)

属性

Microsoft C++ 编译器对 [[gsl::suppress]] 属性的支持有限。 它可用于禁止显示函数内对表达式和块语句的警告。

// Suppress only warnings from the 'r.11' rule in expression.
[[gsl::suppress(r.11)]] new int;

// Suppress all warnings from the 'r' rule group (resource management) in block.
[[gsl::suppress(r)]]
{
    new int;
}

// Suppress only one specific warning number.
// For declarations, you might need to use the surrounding block.
// Macros are not expanded inside of attributes.
// Use plain numbers instead of macros from the warnings.h.
[[gsl::suppress(26400)]]
{
    int *p = new int;
}

使用命令行选项取消分析

在文件的属性页中使用命令行选项来禁止显示项目或单个文件的警告,可以代替使用 #pragmas。 例如,若要禁用文件的警告 C26400,请执行以下操作:

  1. 右键单击“解决方案资源管理器”中的文件,然后选择“属性”

  2. 在“属性页”对话框中,选择“配置属性”>“C/C++”>“命令行”属性页。

  3. 在“其他选项”编辑框中,添加 /wd26400

可以使用命令行选项,通过指定 /analyze- 来暂时禁用文件的所有代码分析。 你将看到警告“D9025 使用"/analyze-"重写"/analyze"”,提醒你稍后重新启用代码分析。

对特定项目文件启用 C++ Core Guidelines 检查器

有时,进行有针对性的代码分析并仍然使用 Visual Studio IDE 是很有用的。 尝试针对大型项目使用以下示例方案。 它可以节省生成时间,更轻松地筛选结果:

  1. 在命令 shell 中,设置 esp.extension 环境变量。

  2. 若要继承此变量,请从命令 shell 打开 Visual Studio。

  3. 加载项目并打开其属性。

  4. 启用代码分析,选择适当的规则集,但不启用代码分析扩展。

  5. 转到你要使用 C++ Core Guidelines 检查器分析的文件,并打开其属性。

  6. 选择“配置属性”>“C/C++”>“命令行”>“其他选项”,并添加 /analyze:plugin EspXEngine.dll

  7. 禁用预编译标头(“配置属性”>“C/C++”>“预编译标头”)。 这是必要的,因为扩展引擎可能会尝试从预编译标头 (PCH) 中读取其内部信息。 如果 PCH 是使用默认项目选项编译的,它将不兼容。

  8. 重新生成项目。 常见的 PREFast 检查应在所有文件上运行。 由于默认情况下未启用 C++ Core Guidelines 检查器,因此它应仅在配置为使用它的文件上运行。

如何在 Visual Studio 外部使用 C++ Core Guidelines 检查器

可以在自动生成中使用 C++ Core Guidelines 检查。

MSBuild

Native Code Analysis 检查器 (PREfast) 由自定义目标文件集成到 MSBuild 环境中。 可以使用项目属性来启用它,并添加 C++ Core Guidelines 检查器(基于 PREfast):

  <PropertyGroup>
    <EnableCppCoreCheck>true</EnableCppCoreCheck>
    <CodeAnalysisRuleSet>CppCoreCheckRules.ruleset</CodeAnalysisRuleSet>
    <RunCodeAnalysis>true</RunCodeAnalysis>
  </PropertyGroup>

请确保在导入 Microsoft.Cpp.targets 文件之前添加这些属性。 可以选择特定的规则集或创建自定义规则集。 或者,使用包含其他 PREfast 检查的默认规则集。

只能在指定的文件上运行 C++ Core 检查器。 使用与前面所述相同的方法,但使用 MSBuild 文件。 可以使用 BuildMacro 项来设置环境变量:

<ItemGroup>
    <BuildMacro Include="Esp_Extensions">
      <EnvironmentVariable>true</EnvironmentVariable>
      <Value>CppCoreCheck.dll</Value>
    </BuildMacro>
</ItemGroup>

如果不想修改项目文件,可以在命令行上传递属性:

msbuild /p:EnableCppCoreCheck=true /p:RunCodeAnalysis=true /p:CodeAnalysisRuleSet=CppCoreCheckRules.ruleset ...

非 MSBuild 项目

如果使用不依赖于 MSBuild 的生成系统,仍可以运行检查器。 若要使用它,需要熟悉 Code Analysis 引擎配置的一些内部结构。 我们不保证在未来版本的 Visual Studio 中支持这些内部结构。

Code Analysis 需要几个环境变量和编译器命令行选项。 建议使用本机工具命令提示符环境,这样就不必搜索编译器的特定路径、包含目录等。

  • 环境变量

    • set esp.extensions=cppcorecheck.dll 这会告知引擎加载 C++ Core Guidelines 模块。
    • 从 Visual Studio 2019 开始,不再建议设置 esp.annotationbuildlevel 环境变量,因为设置可能会导致误报。 如果看到意外的结果,请从环境中删除此变量。
    • set caexcludepath=%include% 强烈建议禁用对标准标头触发的警告。 可以在此处添加更多路径,例如项目中通用标头的路径。
  • 命令行选项

    • /analyze 启用代码分析(同时考虑使用 /analyze:only/analyze:quiet)。
    • /analyze:plugin EspXEngine.dll 此选项将 Code Analysis 扩展引擎加载到 PREfast 中。 反过来,此引擎会加载 C++ Core Guidelines 检查器。

使用准则支持库

准则支持库 (GSL) 旨在帮助你遵循 Core Guidelines。 GSL 包括一些定义,可以让你用更安全的方法来替换容易出错的结构。 例如,可以将一对 T*, length 参数替换为 span<T> 类型。 GitHub 上提供了 GSL 项目,网址为 https://github.com/Microsoft/GSL。 该库是开源的,因此可以查看源代码、发表评论或参与。 还可以使用 vcpkg 包管理器下载并在本地安装该库。

在 Visual Studio 2015 项目中使用 C++ Core Check 准则

如果使用 Visual Studio 2015,则默认情况下不会安装 C++ Core Check 代码分析规则集。 在 Visual Studio 2015 中启用 C++ Core Check 代码分析工具之前,需要执行其他步骤。 Microsoft 使用 NuGet 包为 Visual Studio 2015 项目提供支持。 该包名为 Microsoft.CppCoreCheck,可在 http://www.nuget.org/packages/Microsoft.CppCoreCheck 获得。 此包要求至少安装了 Visual Studio 2015 Update 1。

该包还会安装另一个包作为依赖项,即仅标头准则支持库 (GSL)。 GSL 也在 GitHub 上提供,网址为 https://github.com/Microsoft/GSL

由于代码分析规则在 Visual Studio 2015 中加载的方式,必须将 Microsoft.CppCoreCheck NuGet 包安装到要检查的每个 C++ 项目中。

将 Microsoft.CppCoreCheck 包添加到 Visual Studio 2015 中的项目

  1. 在“解决方案资源管理器”中,右键单击打开你要添加包的解决方案中的项目的上下文菜单。 选择“管理 NuGet 包”以打开“NuGet 包管理器”。

  2. 在“NuGet 包管理器”窗口中,搜索 Microsoft.CppCoreCheck。

    Nuget Package Manager window showing the CppCoreCheck package.

  3. 选择 Microsoft.CppCoreCheck 包,然后选择“安装”按钮,将规则添加到项目。

    NuGet 包将 MSBuild .targets 文件添加到你在项目上启用代码分析时调用的项目。 .targets 文件将 C++ Core Check 规则添加为 Visual Studio Code 分析工具的另一个扩展。 安装包后,可以使用“属性页”对话框启用或禁用已发布的规则和实验性规则。

另请参阅