这篇文章是由Sergiy Oryekhov写的。
在Visual Studio 2017版本15.5预览版4中,我们刷新了 C++核心指南检查 本机代码静态分析工具的扩展。15.3以来的大部分工作都集中在新的规则上,这些规则将帮助开发人员启动新项目,编写更安全的C++,那些有遗留项目的人走向更安全、更现代的C++。对于那些不熟悉核心准则检查的人,我们建议审查最新版本的工作草案: C++核心指南 “.
本文概述了VS2017 15.5中的更改。有关当前版本的更多信息,请参阅 docs.microsoft.com上支持的规则集 .
请注意,docs.microsoft.com的某些链接尚未解析。并不是所有的官方文件都是针对这个主题编写的。
新规则集
在上一版本中,我们引入了几个规则集,以允许客户缩小代码分析结果的范围。为15.5实现的规则扩展了一些现有的规则集(原始指针、所有者指针、唯一指针、类型),还引入了一些新的类别:
- 班级规则 :本节包括一些规则,主要侧重于正确使用特殊方法和虚拟规范。这是建议的检查子集 类和类层次结构 .
- 并发规则 :这当前包括一个捕获错误声明的保护对象的规则。有关更多信息,请参阅 与并发相关的核心准则 .
- 申报规则 :以下是来自 接口 关注如何声明全局变量的指南。
- 函数规则 :这两个检查有助于采用
noexcept
说明符。这是明确的指导方针的一部分 功能设计与实现 . - 共享指针规则 :作为 资源管理 在实施指南中,我们添加了一些特定于如何将共享指针传递到函数或在本地使用的规则。
- 样式规则 :在这个版本中,我们有一个简单但重要的检查,禁止使用
goto
. 这是改进编码风格和使用 表达式和语句 在C++中。但在法律上也有例外 C++核心指南goto
,正确使用这个结构是非常罕见的,值得检讨。
每套新规则
-
班级规则
- C26432定义或删除特殊操作 特殊操作(例如析构函数或复制构造函数)意味着特殊的行为,并且应该以完整的方式来定义这种行为。
- C26436需要虚拟数据 拥有虚拟方法意味着多态行为,这需要更仔细地管理对象清理。
- C26434不隐藏方法 按名称隐藏方法就像隐藏变量一样。命名不应导致歧义。
-
并发规则
- C26441无未命名的守卫 必须将保护对象分配给具有适当作用域的局部变量,并且决不能将其作为临时变量。此规则试图针对在讨论中提到的最常见的锁误用情况 CPPCon 2017:路易斯白兰地“好奇地重复脸谱网上的C++错误” .
-
申报规则
- C26426无u全局u初始化u调用 由于未定义初始化顺序,从全局变量的初始值设定项调用函数可能会导致意外结果。
- C26427无全局初始化外部 全局变量不应引用外部符号,以避免初始化顺序问题。
-
函数规则
- C26439特殊情况 一些特殊函数(比如析构函数)应该避免抛出异常。
- C26440声明无异常 如果一个函数既不抛出也不调用其他可以抛出的函数,则应将其标记为
noexcept
.
-
资源管理规则
- C26416无值参考共享PTR 通过rvalue引用传递共享指针是不必要的,通常表示滥用了共享指针。共享指针传递值既安全又便宜。
- C26417无左值参考共享 通过引用传递的共享指针充当输出参数,预期其所有权将在函数中更新(例如,通过调用
reset()
). 如果共享指针仅用于访问其包含的对象,则应传递指向包含对象的普通引用或指针。 - C26418无值共享 当共享指针通过值或引用传递给const时,它向调用者指示函数需要控制其包含对象的生存期,而不影响调用代码。但是,如果智能指针从未被复制、移动或以其他方式修改,从而影响所包含对象的生存期,则应传递指向所包含对象的普通引用或指针。
- C26415不需要智能PTR 智能指针便于资源管理,但当它们仅用于访问包含的对象时,可以通过向包含的对象传递普通引用或指针来简化代码。
- C26414复位u本地u智能u PTR 使用本地智能指针意味着函数需要控制包含对象的生存期。如果函数不使用智能指针在函数外部传递所有权,并且没有显式调用来更改所有权,则应使用堆栈分配的局部变量来避免不必要的堆分配。
- C26429使用u NOTNULL 如果指针被取消引用,但从未测试过是否为空,那么使用
gsl::not_null
因此,对其有效性的假设是正确的。 - C26430在所有路径上测试 如果一个指针在至少一个路径中被取消引用和测试,那么代码应该确保它在所有路径上都被测试,因为测试意味着指针可能为空。
- C26431不测试不为空 测试gsl::not u null类型的表达式的空值显然是不必要的。
-
样式规则
- C26438不走 现代C++永远不应该使用
goto
在用户编写的代码中。
- C26438不走 现代C++永远不应该使用
-
类型规则
- C26437不切块 即使编译器允许隐式切片,它通常是不安全的和不可维护的。
- C26472无运算转换 静态强制转换可以默默地丢弃不适合算术类型的数据。
- C26473无身份铸造 在完全相同类型的指针之间进行强制转换显然是不必要的。
- C26474无铸件 在隐式完成指针转换的情况下,应该省略强制转换。注意,规则ID有点误导:应该解释为“在可以接受的地方不使用隐式强制转换”。
- C26475无功能类型 函数样式转换是C样式转换的另一种形式,可以导致静默数据截断。
重新排列的警告
VS2017 15.3版中的某些警告号在VS2017 15.5版中不再可用。这些警告并没有消失,而是被更具体的检查所取代。其主要目标是将警告中特别常见的模式分离为单独的警告。
- C26461使用常量输入参数 替换为更具体的警告:
- C26470否u重新解释u CAST u TO u VOID u PTR 已被删除,并由两个新警告的部分逻辑替换。同样地, C26490无需重新解释铸件 已缩小范围,仅涵盖这些新警告未涵盖的情况。
- C26496使用u CONST u作为u变量 缩小到非指针值;其余的则分为特定的警告:
- C26492无施工铸件 缩小到有效的铸型;对于其他情况,有具体的警告:
- C26491无静态下行 局限于非多态类型;多态类型强制转换由特定警告标记:
最后
好的工具可以帮助您维护和升级代码。C++核心指南是一个很好的开始,C++核心指南检查器可以帮助您清理代码并保持代码整洁。试用VisualStudio 2017版本15.5中的扩展C++核心指南检查器,让我们知道您的想法。
如果您对我们有任何反馈或建议,请告知我们。我们可以通过以下评论和电子邮件联系到您( visualcpp@microsoft.com )你可以通过 帮助>报告产品中的问题 ,或通过 开发者社区 . 你也可以在Twitter上找到我们( @视觉 )还有Facebook( msftvisualcpp软件 ).