Visual Studio 2019 does not handle aggregate initialization of dynamic array of structs correctly
Asked Answered
P

1

26

The code below prints garbage (or zeroes) if compiled with VC++ 2017 and "1122" if compiled with GCC or Clang (https://rextester.com/JEV81255). Is it bug of VC++ or I'm missing something here?

#include <iostream>

struct Item {
    int id;
    int type;
};

int main()
{
    auto items = new Item[2]
    {
        { 1, 1 },
        { 2, 2 }
    };

    std::cout << items[0].id << items[0].type;
    std::cout << items[1].id << items[1].type;
}

At the same time it works if elements are of a primitive type (like int).

Porism answered 4/9, 2019 at 10:41 Comment(7)
Yeah, it has been broken for several years. The stuff inside {} is completely ignored so you can write some nonsense like auto items = new Item[2] { { std::cout, " sdf" , 0.3f} };. I've tried to find related issues at VS feedback hub (at least the one I've created) but the search there is broken as well...Subtorrid
Following up @VTT comment still very broken, live: godbolt.org/z/Fn6dgpIstanbul
@rafix07 It is still broken in VS2019Subtorrid
VS2019 Code Analysis gives: warning C6001: Using uninitialized memory 'items[0].id'. But clang-cl inside VS2019 works fine.Maccarone
That's scary. And the fact MS doesn't fix this is even more scary...Fiesole
This works with std::vector but not std::array. The pre-compiler complains of "too many initializer values" and the actual compiler throws a C2440 error with the note: "Invalid aggregate initialization." The above code as-is only warns about accessing unintialized memory.Scamp
This is fixed in MSVC 19.27.Fireboat
S
1

I got it to work by writing the following but then the data is not stored on the Heap.

Item items[] {
    { 1, 1 },
    { 2, 2 }
};

If you need it on the heap use the solution below it seems to work with the vc++ compiler. (Note that this is only a workaround and does nt fix the underlying problem):

Item* Items[2];
Items[0] = new Item{3,3};
Items[1] = new Item{4,4};

std::cout << (*Items[0]).id << (*Items[0]).type << std::endl;
std::cout << (*Items[1]).id << (*Items[1]).type << std::endl;

Altenatively you can create the Array using the first option and then copy it into an Array on the heap like this:

Item items[2]{
    {1,1},
    {2,2}
};

Item* hitem = new Item[2];
for(int i = 0; i < 2; i++){
    hitem[i].id = items[i].id + 4;
    hitem[i].type = items[i].type + 4;
}

While this is slow it works like it is supposed to even on the vc++ compiler. You can view the whole code here:https://rextester.com/VNJM26393

I don't know why it only works like this...

Stadiometer answered 10/9, 2019 at 16:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.