在使用 /O2、/Ob2、/arch:AVX2 标志编译以下代码后,我遇到了一个错误。我在 Win64 上使用 Microsoft Visual Studio Community 2019 版本 16.4.6。
运行以下代码会产生以下输出。请注意第一行和第三行的中间列:
(1) NOT OK (Line 0 != Line 2) :
000001B5B43B07D0 000001B5B43BD9D0 000001B5B43BDA10
000001B5B43B07E8 000001B5B43BD9DC 000001B5B43BDA1C
000001B5B43B07D0 000001B5B43BD9DC 000001B5B43BDA1C
000001B5B43B07E8 000001B5B43BD9DC 000001B5B43BDA1C
在第一个循环中,我们得到000001B5B43BD9D0
for malloc() + 0 * (6/2)
。但是在同一个循环的第二个副本中,我们得到...C
了地址。结果...0
是正确的,因为 malloc 在 Windows x64 上返回一个 16 字节对齐的指针。 0 * (6/2)
为 0。
第三列也有同样的问题。
看起来问题与我在第 22、23、24、30、31、32 行收到的以下警告有关。将变量l
转换为 int64_t 时,我摆脱了这个问题。
警告 C26451 算术溢出:对 4 字节值使用运算符 *,然后将结果转换为 8 字节值。在调用 operator * 之前将值转换为更广泛的类型以避免溢出 (io.2)。
没关系,我可以这样解决问题,但我想了解这里到底发生了什么。对于具有相同编译标志的 gcc,我不会遇到这个问题。
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define N_TESTS 1
#define W 6
#define H 2
int main() {
int k, l;
int32_t* mock_ptrs[3];
int32_t* mock_out_ref[3];
mock_out_ref[0] = malloc(H * W * sizeof(int32_t));
mock_out_ref[1] = malloc(H * W * sizeof(int32_t));
mock_out_ref[2] = malloc(H * W * sizeof(int32_t));
printf("(1) NOT OK (Line 0 != Line 2) : \n");
for (k = 0; k < N_TESTS; k++) {
for (l = 0; l < H; l++) {
mock_ptrs[0] = mock_out_ref[0] + l * W;
mock_ptrs[1] = mock_out_ref[1] + l * (W/2);
mock_ptrs[2] = mock_out_ref[2] + l * (W/2);
printf("%p %p %p\n", mock_ptrs[0], mock_ptrs[1], mock_ptrs[2]);
}
}
for (k = 0; k < N_TESTS; k++) {
for (l = 0; l < H; l++) {
mock_ptrs[0] = mock_out_ref[0] + l * W;
mock_ptrs[1] = mock_out_ref[1] + l * (W/2);
mock_ptrs[2] = mock_out_ref[2] + l * (W/2);
printf("%p %p %p\n", mock_ptrs[0], mock_ptrs[1], mock_ptrs[2]);
}
}
free(mock_out_ref[0]);
free(mock_out_ref[1]);
free(mock_out_ref[2]);
return 0;
}