C ++代码分析:命令行配置规则

[原文发表地址]:C++ code analysis: configure rules from the command line

[原文发表时间]:2018年4月9日

[作者]:Sunny Chatterjee 和 Andrew Pardoe

这篇文章由Sunny Chatterjee和Andrew Pardoe撰写。

Visual Studio 15.7预览版3引入了一个新的MSVC编译器开关,/analyze:ruleset用于配置代码分析运行。 此开关的主要目的是用以支持使用C ++代码分析而不使用MSBuild过滤规则的开发人员。 但是,使用MSBuild进行代码分析的开发人员也从这种开关中受益:代码分析运行速度更快,从而提高了编译吞吐量。

什么是代码分析规则集?

代码分析规则集允许您选择在分析代码时看到的代码分析结果。 代码分析规则集可以在项目>属性>代码分析>常规 中找到。 默认情况下,新的C ++项目已选择规则集“Microsoft Native Recommended Rules”

您可以从突出显示的下拉列表中选择您希望应用于项目的规则集。

Visual Studio附带了一些您可以选择的内置规则集。 它们位于%VSINSTALLDIR%\ Team Tools \ Static Analysis Tools \ Rule Sets中。 我们正在增加这套规则 - 请继续关注VC博客,了解更多信息。

您也可以创建自己的自定义规则集并将其应用于您的项目。 要创建自定义规则集,请转至文件>新建>文件>常规>代码分析规则集。

在Visual Studio 2017 15.7版预览版3之前,每次运行C ++代码分析时都会运行所有规则。 当您为给定项目运行代码分析时,像C ++ Core Check这样的检查器会生成一个缺陷列表。 代码分析完成后,会有一个MSBuild任务将缺陷列表合并到一起,并根据为项目选择的规则集对其进行过滤。 您只会显示适用于您当前所选代码分析规则集的警告。

如果您在VS环境中构建旧的机制,那么这个旧机制很有效,但有一些地方不足。 首先,如果您在自定义构建环境中使用VS编译器工具集,则不会通过规则集获得任何配置选项。 您必须根据需要过滤的缺陷来编写自己的工具。 其次,在当前的VS环境中,规则集过滤机制本质上是一种后期处理工具 - 检查工具完成所有工作以生成缺陷,最终将其过滤掉。 我们在MSVC编译器工具集中添加 /analyze:ruleset以克服代码分析体验中的这些缺陷。

/analyze:ruleset 是如何工作的?

新的/ analyze:ruleset选项可以用于任何构建配置:VS内部或外部,使用MSBuild,Ninja或自定义构建系统。 这个新选项允许编译器根据规则集中指定的一组规则直接过滤缺陷。 现在编译器已经知道哪些规则是活动的,它可以将这些知识传递给各个检查器,以便他们做出明智的决定。 例如,如果规则集仅指定类型安全的规则,像生命周期这样的代价更高的检查可以自行关闭,所以您只需付出分析成本方面的成本。 不必运行未选定的规则意味着您的代码分析体验更快,更流畅。

使用 /analyze:ruleset

利用这个新开关很简单:只需定义自己的规则集文件,并在运行代码分析时将该选项传递给编译器。 这是一个最好循序渐进的例子, 在这个例子中,我们将检测程序中所有与未初始化变量相关的缺陷。

  • 首先,我们需要确定一组将检测未初始化的变量和内存的规则。 对于这个例子,我们选择了两条可以帮助我们的规则,C6001和C26494。

  • 现在需要创建一个规则集文件,其中包含您选择的一组规则。 我们可以在如上所示的Visual Studio中执行此操作,或者我们可以通过编写简单的XML来手动创建规则集。

  • 现在我们有一个如下所示的规则集文件,我们已将其保存为UninitVariable.ruleset。

  • 对于这个例子,我们的测试文件如下所示。 我们将其命名为test.cpp。

  • 我们运行没有任何配置选项的代码分析并观察以下警告:

    E:\test>cl.exe /c test.cpp /analyze:plugin EspXEngine.dll

    Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26329 for x86

    Copyright (C) Microsoft Corporation.  All rights reserved.

    test.cpp

    e:\test\test.cpp(8) : warning C6001: Using uninitialized memory 'i'.: Lines: 3, 4, 8

    e:\test\test.cpp(3) : warning C26494: Variable 'i' is uninitialized. Always initialize an object (type.5).

    e:\test\test.cpp(1) : warning C26497: The function 'f' could be marked constexpr if compile-time evaluation is desired (f.4).

    e:\test\test.cpp(1) : warning C26440: Function 'f' can be declared 'noexcept' (f.6).

  •  接下来,我们传递额外的编译器选项来指定我们的自定义规则集来识别未初始化的变量:/ analyze:ruleset UninitVariable.ruleset。

E:\test>cl.exe /c test.cpp /analyze:plugin EspXEngine.dll /analyze:ruleset UninitVariable.ruleset

Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26329 for x86

Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp

e:\test\test.cpp(8) : warning C6001: Using uninitialized memory 'i'.: Lines: 3, 4, 8

e:\test\test.cpp(3) : warning C26494: Variable 'i' is uninitialized. Always initialize an object (type.5).

使用/ analyze:ruleset选项,代码分析仅运行未初始化变量的规则,并且与这些规则无关的其他警告不再显示。

最后

我们希望您会发现/analyze:ruleset选项对于在您的私有构建环境中配置代码分析运行是有用的。 我们已经开始利用它了! 例如,我们在Visual Studio中代码分析的目标文件, 现在运行代码分析时将/ analyze:ruleset选项传递给编译器。 这样我们可以根据选定的规则集优化我们的检查。 我们将在未来推出新的默认规则集,并在Visual Studio中提供支持,以在CMake for Ninja和Visual Studio等构建环境中运行C ++代码分析。

同平时一样,我们欢迎您的反馈。 我们可以通过下面的评论或通过电子邮件(visualcpp@microsoft.com)联系到。

如果您在Visual Studio 2017中遇到MSVC的其他问题,请通过帮助>报告产品中的问题或通过开发者社区告诉我们。 让我们通过UserVoice了解您的建议。 您还可以在Twitter(@VisualC)和Facebook(msftvisualcpp)上找到我们。