Issue
I have a header file defined as
#pragma once
#include <iostream>
template<int size>
struct B
{
double arr[size * size];
constexpr B() : arr()
{
arr[0] = 1.;
}
};
template<int size>
struct A
{
const double* arr = B<size>().arr;
void print()
{
// including this statement also causes undefined behaviour on subsequent lines
//printf("%i\n", arr);
printf("%f\n", arr[0]);
printf("%f\n", arr[0]); // ???
// prevent optimisation
for (int i = 0; i < size * size; i++)
printf("%f ", arr[i]);
}
};
and call it with
auto a = A<8>();
a.print();
Now this code only runs expectedly when compiled with msvc release mode (all compiled with c++17).
expected output:
1.000000
1.000000
msvc debug:
1.000000
-92559631349317830736831783200707727132248687965119994463780864.000000
gcc via mingw (with and without -g
):
1.000000
0.000000
However, this behaviour is inconsistent. The expected output is given if I replace double arr[size * size]
with double arr[size]
instead. No more problems if I allocate arr
on the heap of course.
I looked at the assembly of the msvc debug build but I don't see anything out of the ordinary. Why does this undefined behaviour only occur sometimes?
Solution
It seems that it was completely coincidental that smaller allocations were always addressed in a spot that would not get erased by the rep stosd
instruction present in printf. Not caused by strange compiler optimisations as I first thought it was.
What does the "rep stos" x86 assembly instruction sequence do?
I also have no idea why I decided to do it this way. Not exactly the question I asked but I ultimately wanted a compile time lookup table so the real solution was static inline constexpr auto arr = B<size>()
on c++20. Which is why the code looks strange.
Answered By - mmmm Answer Checked By - Mary Flores (WPSolving Volunteer)