使用 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 本机建议规则集中。 它是启用代码分析时默认运行的规则集。
在项目上启用代码分析
打开项目的“属性页”对话框。
选择“配置属性”>“Code Analysis”属性页。
选中“生成时启用 Code Analysis”复选框。
若要启用更多 Core Check 规则,请打开下拉列表,然后选择要包括的规则集:
C++ Core Check 规则的子集包含在 Microsoft 本机建议规则集中。 它是启用 Microsoft 代码分析时默认运行的规则集。
要在项目上启用代码分析,请执行以下操作:
打开项目的“属性页”对话框。
选择“配置属性”>“Code Analysis”属性页。
设置“生成时启用 Code Analysis”和“启用 Microsoft Code Analysis”属性。
还可以选择运行所有受支持的 C++ Core Check 规则,或选择运行你自己的子集:
启用更多 Core Check 规则
打开项目的“属性页”对话框。
选择“配置属性”>“Code Analysis”>“Microsoft”属性页。
打开“活动规则”下拉列表,然后选择“选择多个规则集”。
在“添加或删除规则集”对话框中,选择要包括的规则集。
示例
下面是 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 参考下找到大多数规则的参考文章。
算术规则:用于检测算术溢出、signed-unsigned 运算和位操作的规则。15.6
边界规则:强制执行 C++ Core Guidelines 的边界配置文件。15.3
类规则:一些侧重于正确使用特殊成员函数和虚拟规范的规则。 它们是建议用于类和类层次结构的检查的子集。15.5
并发规则:单个规则,捕获错误的防护对象声明。 有关详细信息,请参阅与并发相关的准则。15.5
Const 规则:强制执行 C++ Core Guidelines 中与 const 相关的检查。15.3
声明规则:接口准则中的一些规则,侧重于全局变量的声明方式。15.5
枚举规则:这些规则强制执行 C++ Core Guidelines 中与枚举相关的检查。16.3
实验性规则:这些实验性 C++ Core Check 规则非常有用,但未准备好用于日常用途。 请试用并提供反馈。16.0
函数规则:有助于采用
noexcept
说明符的两项检查。 它们是明确函数设计和实现的准则的一部分。15.5GSL 规则:这些规则强制执行与 C++ Core Guidelines 中的准则支持库相关的检查。15.7
生存期规则:这些规则强制执行 C++ Core Guidelines 的生存期配置文件。15.7
所有者指针规则:强制执行 C++ Core Guidelines 中与所有者<T> 相关的资源管理检查。15.3
原始指针规则:强制执行 C++ Core Guidelines 中与原始指针相关的资源管理检查。15.3
共享指针规则:它是资源管理准则强制执行的一部分。15.5 我们添加了一些特定于共享指针如何传递到函数或在本地使用的规则。
STL 规则:这些规则强制执行与 C++ Core Guidelines 中的 C++ 标准库 (STL) 相关的检查。15.7
样式规则:一项简单但重要的检查,禁止使用 goto。15.5 这是改进编码风格以及 C++ 中表达式和语句的使用的第一步。
类型规则:强制执行 C++ Core Guidelines 的类型配置文件。15.3
唯一指针规则:强制执行 C++ Core Guidelines 中与具有唯一指针语义的类型相关的资源管理检查。15.3
C++ Core Check 规则:此规则集包含 C++ Core Guidelines 中当前实现的所有检查,但实验性规则除外。
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,请执行以下操作:
右键单击“解决方案资源管理器”中的文件,然后选择“属性”。
在“属性页”对话框中,选择“配置属性”>“C/C++”>“命令行”属性页。
在“其他选项”编辑框中,添加
/wd26400
。
可以使用命令行选项,通过指定 /analyze-
来暂时禁用文件的所有代码分析。 你将看到警告“D9025 使用"/analyze-"重写"/analyze"”,提醒你稍后重新启用代码分析。
对特定项目文件启用 C++ Core Guidelines 检查器
有时,进行有针对性的代码分析并仍然使用 Visual Studio IDE 是很有用的。 尝试针对大型项目使用以下示例方案。 它可以节省生成时间,更轻松地筛选结果:
在命令 shell 中,设置
esp.extension
环境变量。若要继承此变量,请从命令 shell 打开 Visual Studio。
加载项目并打开其属性。
启用代码分析,选择适当的规则集,但不启用代码分析扩展。
转到你要使用 C++ Core Guidelines 检查器分析的文件,并打开其属性。
选择“配置属性”>“C/C++”>“命令行”>“其他选项”,并添加
/analyze:plugin EspXEngine.dll
禁用预编译标头(“配置属性”>“C/C++”>“预编译标头”)。 这是必要的,因为扩展引擎可能会尝试从预编译标头 (PCH) 中读取其内部信息。 如果 PCH 是使用默认项目选项编译的,它将不兼容。
重新生成项目。 常见的 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 中的项目
在“解决方案资源管理器”中,右键单击打开你要添加包的解决方案中的项目的上下文菜单。 选择“管理 NuGet 包”以打开“NuGet 包管理器”。
在“NuGet 包管理器”窗口中,搜索 Microsoft.CppCoreCheck。
选择 Microsoft.CppCoreCheck 包,然后选择“安装”按钮,将规则添加到项目。
NuGet 包将 MSBuild
.targets
文件添加到你在项目上启用代码分析时调用的项目。.targets
文件将 C++ Core Check 规则添加为 Visual Studio Code 分析工具的另一个扩展。 安装包后,可以使用“属性页”对话框启用或禁用已发布的规则和实验性规则。