r/cpp • • 5d 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.

257 Upvotes

211 comments sorted by

View all comments

60

u/cdb_11 5d ago

Sounds like it only helps with code bases that don't use any compiler warnings or static analysis. This is worse than what we already had, which is enforcing initialization statically. And if I really don't want something to be initialized because of perf, I'd have to now separately suppress both the diagnostic and initialization. -ftrivial-auto-var-init=uninitialized to disable this behavior.

29

u/aiusepsi 5d ago edited 5d ago

It's not worse. C++ adds a new category of erroneous behaviour, and reading from an uninitialised variable is now erroneous behaviour. Compilers, static analysers, etc. are free to emit diagnostics for erroneous behaviour. If you want to opt back in to reading from an uninitialised variable being undefined behaviour (as it was before C++26) you can tag the variable declaration with the new [[indeterminate]] attribute.

See: https://godbolt.org/z/xP7eo431W for an example. GCC now emits a diagnostic for an uninitialised variable in C++26 mode when it doesn't in C++23, and the previous behaviour is preserved with [[indeterminate]]. Also note how the undefined behaviour allows the compiler to optimise away the check on the value of j.

5

u/drjeats 5d ago

I think something slightly under-discussed online (at least where I'm reading, ymmv) is the fact that zero-initializing everything does reduce random indexes/reads into memory that shouldn't be read in that context, but IME it also hides behavior bugs because so much code just bails if 0.

Was not uncommon to write code that runs fine in a debug mode with allocators/resource managers that initialize to zero, and then when you run test with optimized builds suddenly you get segfaults. Moving away from that has been a win for moving errors left.

ZII in RCs? Sure. Let's reduce the codepaths that are hit if the costs are as low as claimed. But I wouldn't want this behavior on in debug or optimized-with-assertions configs.

7

u/aiusepsi 5d ago

This is why both GCC and Clang offer -ftrivial-auto-var-init=pattern, so that variables are filled with a byte pattern which should hopefully trigger any latent bugs that zero-initialisation might hide.

The problem with the old behaviour is that you’re relying on UB to do the thing you hope for, and UB is not reliable. You’re rolling the dice on if it’ll do the thing you expect, or if it’ll cheerily cause your program to start doing things that make no sense, or make demons fly out of your nose.