我试图理解 Visual Studio 2022 中这一特定建议背后的原因,因为它对我来说似乎没有意义。这是简单的代码:
static constexpr uint32_t MAX_ELEMENTS = 100000;
const std::vector<int> A{ some random ints };
std::vector<bool> found(MAX_ELEMENTS);
for (int value : A)
{
if (value > 0 && value <= MAX_ELEMENTS)
found[value - 1] = true; // Problem it complains about is the value - 1.
}
Run Code Online (Sandbox Code Playgroud)
它表明“子表达式在添加到更广泛的类型之前可能会溢出”。现在显然条件 if 阻止了这种情况的发生,但是这里的推理是什么?
现在,如果这是 Spectre 的事情,我可以理解编译器会添加内存栅栏来停止 if 之后语句的任何推测执行,但我不认为这就是答案。
我唯一的想法是它与向量上的下标运算符有关;它的索引是大于 int 的类型并且隐式转换为 size_t?
下面的问题似乎有点不直观:
found[value - 1]
Run Code Online (Sandbox Code Playgroud)
这样做完全没问题,
int a = value - 1;
found[a];
Run Code Online (Sandbox Code Playgroud)
当最终结果相同时。就理解而言,我在这里缺少什么?
在这种情况下,正如您所怀疑的那样,这是误报。这是有时在更严格的代码库中使用的规则。(例如,此特定警告是 MISRA 中的错误。)
很多警告都是这样的......编译器编写者试图检测程序行为是意外或无意的情况,但警告并不总是正确的。例如,
uint64_t x = 0xffffffffu << 16;
Run Code Online (Sandbox Code Playgroud)
在具有 32 位 int 的系统上,标准非常清楚this 的值应该是什么......它应该是:
uint64_t x = 0xffff0000u;
Run Code Online (Sandbox Code Playgroud)
然而,看起来确实有人打算写这个:
uint64_t x = (uint64_t)0xffff0000 << 16;
Run Code Online (Sandbox Code Playgroud)
这就是警告试图捕捉到的内容。这就是这条规则背后的原因。就您而言,编译器做得很糟糕。
您可以在编译器文档中查看该警告的更详细理由:警告 C26451。
幽灵与此无关。
去做这个:
int a = value - 1;
found[a];
Run Code Online (Sandbox Code Playgroud)
在这种情况下,“意图”更加明显,因为程序员已明确写出“int”作为类型。
这是一个代码风格问题,因此有几种不同的解决方案,您可以选择您觉得舒服的解决方案。
保持警告打开(噪音,可能会分散您对真正警告的注意力)
首先将表达式分配给 int(详细)
禁用整个代码库的警告(如果您认为它没有帮助)
#pragma warning使用(非常详细)禁用此位置周围的警告
| 归档时间: |
|
| 查看次数: |
3359 次 |
| 最近记录: |