我们在Visual Studio 16.10版本预览版3中添加了一个新的实验静态分析规则–C26458, WARNING_PATH_SENSITIVE_USE_GSL_AT
. 新的警告是一个更精确,噪音更小的C26446警告版本, WARNING_USE_GSL_AT
. 这两个警告都分析未检查元素访问的标准容器,它们都共享警告消息:“preferto use gsl::at()
但是,这个新的警告使用路径敏感分析来跟踪缓冲区大小验证调用,与C26446相比,它提供了一个噪音更小、更有针对性的警告。
路径敏感分析不是一种廉价的操作:分析每个函数所需的复杂性和时间取决于分支操作的长度、数量以及每个函数中跟踪的单个属性。路径模拟遍历函数并模拟它遇到的每个分支和循环,根据代码中的各种假设更新内部状态。考虑以下代码段:
int i{}; // ... if (i < v.size()) { // ... } // ...
当模拟到达分支时,分析将分叉其状态。它在一个叉子上跟踪 i
小于 v.size()
,另一个 i
大于或等于 v.size()
. 分析不一定知道 i
或者元素的数量 v
. 只有通过比较才能知道这两者之间的关系。当分析遇到循环时,同样的分支也会发生。
示例和与C26446的比较:
void function(std::vector<int>& v) { if(v.size()) v[0]; // C26446 v[0]; // C26446 and C26458 }
在路径敏感检查中,一个分支知道 v
不是空的,证明访问第一个元素是安全的,但是在另一个元素中, v
为空,这就是第二个访问发出警告的原因。另一方面,C26446将在任何情况下发出警告 operator[]
电话不是由 gsl::span
.
为什么这个检查是实验性的,它不能做什么?
目前,C26458不跟踪容器的扩展。这意味着 push_back
, emplace
, insert
,等还不受支持。它也不跟踪元素的移除。但是,与容器的扩展不同,缩减需要容器边界的完全重新验证。在将来的更新中,将添加对容器扩展/缩减的支持。
void function(std::vector<int>& v) { if (v.size() > 2) { v[2]; // C26446 v.push_back(0); v[2]; // C26446 v[3]; // C26446 & C26458 v.erase(v.begin()); // element removal currently removes all assumptions for the container v[2]; // 26446 & C26458 } }
如何启用C26458
在Visual Studio中启用规则:
在Project属性页面中:导航到配置属性->代码分析->微软,并选择C++核心指南实验规则。
或者,可以将当前规则集配置为包含C26458。
我们建议用户在使用C26458时禁用C26446,以避免重复警告。
反馈和跟进:
让我们知道你的经验与新的检查,我们渴望听到你们所有人回来。另外,如果您希望在将来看到更多这样的路径敏感规则,请告诉我们。请下载最新版本 Visual Studio 2019 试试看!欢迎任何反馈。我们可以通过以下评论联系到您, 开发者社区 , 电子邮件 ,和 推特 .