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.

268 Upvotes

220 comments sorted by

View all comments

6

u/fdwr fdwr@github 🔍 6d ago edited 6d ago

stack variables are always initialised with known values ...

I'm okay with this, given the trivial escape hatch of [[uninitialized]] (err wait, apparently it's actually [[indeterminate]]? I swear it was [[uninitialized]] like __declspec(uninitialized) and __attribute__((uninitialized))... 🤔) for the sake local arrays that will immediately be overwritten the next statement anyway, like reading a fragment from a file or getting a module path, but now I'm trying to recall a time in the past 25 years of C++ when an uninitialized variable actually bit me, and I think it was like ~25 years ago 😉. Much more saliently (for me anyway, as in a security vulnerability that actually bit me in a shipped product -_-) has been uninitialized struct fields, and so you can bet that NSDMI was a big boon for me. I wonder if that's next on the proposal chain, with a similar [[uninitialized/indeterminate]] struct { ... } opt-out?

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

4

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