I struggle with a bug since hours now. Basically, I do some simple bit operation on an uint64_t array in main.c (no function calls). It works properly on gcc (Ubuntu), MSVS2019 (Windows 10) in Debug, but not in Release. However my target architecture is x64/Windows, so I need to get it work properly with MSVS2019/Release. Besides that, I'm curious what the reason for the problem is. None of the compilers shows errors or warnings.
Now, as soon as I add a totally unrelated command to the loop (commented printf()
), it works properly.
...
int q = 5;
uint64_t a[32] = { 0 };
// a[] is filled with data
for (int i = 0; i < 32; i++) {
a[q] = (a[q] << 2) | 8;
// printf("%i \n", i); // that's the line which makes it work
}
...
Initially I believed that I messed up the stack somewhere before the for()
loop, but I checked it up multiple times ... all fine!
- all used variables are checked to be initialized
- no pointer returns of local variables (in scope)
- array indexing (reads and writes) all within declaration limits (in scope)
All Google/SE posts explain subject UB to some of the above reasons, but none of these apply for my code. Also the fact, that it works in MSVS2019/Debug and gcc shows the code works.
What do I miss?
--- UPDATE (24.08.2021 12:00) ---
I'm completely stuck, since added printf()
modifies the result and MSVS/Debug works. So how can I inspect variables?!
@Lev M There are quite some calculations before and after the shown for()
loop. That's why I skipped most of the code and just showed the snippet where I could influence the code towards working correctly. I know what should be the final result (it's just a uint64_t), and it's wrong with the Release version of MSVS. I also checked w/o the for()
loop. It's not optimized "away". If I leave it out completely, the result is again different.
@tstanisl It's just a matter of an uint64_t number. I know that input A should output B.
@Steve Summit That's why I posted (a bit desperate). I checked in all directions, isolated as much code as I could and yet ... no uninitialized variable or array out of bound. Driving me nuts.
@Craig Estey The code is unfortunately quite extensive. I wonder ... could the error also be in a part of the code which doesn't run?
@Eric Postpischil Agreed!
@Nate Eldredge I tested on valgrind (see below).
...
==13997== HEAP SUMMARY:
==13997== in use at exit: 0 bytes in 0 blocks
==13997== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==13997==
==13997== All heap blocks were freed -- no leaks are possible
==13997==
==13997== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
--- UPDATE (24.08.2021 18:00) ---
I found the reason for the problem (after countless trial-and-errors), but no solution yet. I post more of the code.
...
int q = 5;
uint64_t a[32] = { 0 };
// a[] is filled with data
for (int i = 0; i < 32; i++) {
a[q] = (a[q] << 2) | 8;
// printf("%i \n", i); // that's the line which makes it work
}
for (int i = 0; i < 32; i++) {
a[q] = (a[q] << 3) | 3;
}
...
In fact, the MSVS/Release compiler did this:
...
int q = 5;
uint64_t a[32] = { 0 };
// a[] is filled with data
for (int i = 0; i < 32; i++) {
a[q] = (a[q] << 2) | 8;
a[q] = (a[q] << 3) | 3;
}
...
... which is not the same. Never seen such a thing!
How can I force the compiler to keep the 2 for()
loops separate?