MSVC 刚刚发布了一个更新,其中添加了一个关于编译器将注入的一些代码的新警告,以减轻(显然是一些小部分)Spectre:
https://blogs.msdn.microsoft.com/vcblog/2018/01/15/spectre-mitigations-in-msvc/
这是从他们的“有问题的”代码示例中得出的一个小 MCVE:
#include <stdio.h>
int main(int argc, char *argv) {
unsigned char array1[1] = {0};
int array1_length = 1;
unsigned char array2[1] = {99};
int untrusted_index = 0; /* in this MCVE, I trust it, compiler doesn't */
for (; untrusted_index < array1_length; ++untrusted_index) {
unsigned char value = array1[untrusted_index];
unsigned char value2 = array2[value * 64];
printf("Picked value %d\n", value2);
}
return 0;
}
“在上面的示例中,代码执行数组边界检查以确保 untrusted_index 小于 array1 的长度。这是确保程序不会读取超出数组边界所必需的。虽然这似乎是合理的正如所写的那样,它没有考虑 CPU 涉及推测执行的微架构行为。”
所以你现在得到一个警告:
警告 C5045:如果指定 /Qspectre 开关,编译器将插入 Spectre 缓解内存负载
这是它告诉您此代码最终可能比您希望的要慢(如果编译/Qspectre)的方式,因为它将提供一些额外的保护。
由于您似乎无法将任何事情视为理所当然,因此我怀疑做出“只是让警告消失”的更改。例如,对于我在此处给出的 MCVE 代码的特定实例,更改untrusted_index < array1_length
为untrusted_index != array1_length
似乎可以做到这一点。但这是一个可行的补丁,还是他们的警告只是不完整的——在下一次更新中,它也会抱怨这个?
我知道我可以使用 /wd5040 或其他方式禁用警告。但我有兴趣确保如果代码是使用 /Qspectre 编译的,则不会出现减速,并且如果代码不是使用 /Qspectre 编译的,则不会出现警告。我不想到处触摸文件更改<
为!=
循环条件 - 或其他 - 如果这只是流失。
所以一个更大的问题是,如果有这种基本的合法解决方法模式,为什么没有提到它们?例如,我描述的情况是我控制索引的迭代,不必担心它来自“不受信任的来源”。然而我得到了一个警告,从 切换<
到!=
让它消失了。为什么?应该有吗?