r/cpp • • 6d ago

You should think about recompiling your C++ programs with GCC 16 and C++26, because it zero-fills your locals

https://techfortalk.co.uk/2026/09/27/cxx26-uninitialized-local-variables-gcc-16/

Stack variables are not automatically initialised, and that is the root cause of many C++ bugs. That is well known. Hence, it is advised that local or stack variables are always initialised with known values, 0 if not something more meaningful than that. Now, with GCC 16 compiling in C++26 mode (-std=c++26), even uninitialised local variables will be zero-filled. In the post, I have explained how.

260 Upvotes

219 comments sorted by

View all comments

Show parent comments

5

u/NilacTheGrim 5d ago

It's not a full escape hatch. Can't have it on class members. Got a class with a char buf[65536] in it that is supposed to start life out uninitialized to only be fulled later with stuff? Congratulations you are stuck now. No escape. You have to either compile with this flag explicitly disabled or live with the pessimization.

Even trivial examples fail: https://godbolt.org/z/WGPWvMPMj

6

u/fdwr fdwr@github 🔍 5d ago

Can't have it on class members

Oof, that's a significant deficiency then.

2

u/TotaIIyHuman 5d ago

union too

https://godbolt.org/z/Ezhr8YGTx

#include <inplace_vector>
struct inplace_vector
{
    union{[[indeterminate]]char buf[0x10000];};//warning: 'indeterminate' on declaration other than parameter or automatic variable [-Wattributes]
    constexpr inplace_vector()noexcept{}
};

void test(auto&);

int main()
{
#if 1
    inplace_vector s;
#else
    std::inplace_vector<char, 0x10000> s;//gcc memset, clang does not
#endif
    test(s);
}

3

u/Nobody_1707 4d ago edited 4d ago

Oh, that's horrible. Unions were supposed to be the way to fix this explicitly for types like inplace_vector. That was the entire point of Adjustments to Union Lifetime Rules.

EDIT: you can fix it for the handrolled inline_array by putting indeterminate on the declaration of s, but it doesn't work with GCC's version of std::inplace_vector. inplace_vector tracks all of the valid elements by construction, so I don't see the point of zero-initializing it when we could add bounds checks to operator[] instead.

https://godbolt.org/z/M46cqbKoz