Sunday, April 10, 2022

[SOLVED] Undefined behaviour accessing const ptr sometimes

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?

asm output

decompiled msvc release


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)