I’m having a bug after compiling the below piece of code with /O2, /Ob2, /arch:AVX2 flags. I am using Microsoft Visual Studio Community 2019 Version 16.4.6 on a Win64.
Running the below piece of code results in the following output. Note the middle column in the first and third lines:
(1) NOT OK (Line 0 != Line 2) :
000001B5B43B07D0 000001B5B43BD9D0 000001B5B43BDA10
000001B5B43B07E8 000001B5B43BD9DC 000001B5B43BDA1C
000001B5B43B07D0 000001B5B43BD9DC 000001B5B43BDA1C
000001B5B43B07E8 000001B5B43BD9DC 000001B5B43BDA1C
In the first loop, we get 000001B5B43BD9D0
for malloc() + 0 * (6/2)
. But in the second copy of the same loop we get ...C
for the address. The ...0
result is correct because malloc returns a 16-byte aligned pointer on Windows x64. 0 * (6/2)
is 0.
The 3rd column has the same problem.
It looks like the problem is related with the below warning I get at lines 22, 23, 24, 30, 31, 32. When casting the variable l
to int64_t, I get rid of this problem.
Warning C26451 Arithmetic overflow: Using operator * on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator * to avoid overflow (io.2).
It’s OK, I can fix the problem that way but I’d like to understand what is really going on here. I don’t face this problem with gcc with the same compile flags.
#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;
}