On Mon, Mar 10, 2025 at 5:36 AM Giuseppe D'Angelo via Std-Discussion <std-discussion@lists.isocpp.org> wrote:

I think there's a misunderstanding here: EB doesn't mandate that the
storage for an automatic variable gets initialized in any specific way.
It just changes the semantics of what happens if you read from an
uninitialized automatic variable (you get EB). The [[indeterminate]]
attribute restores the pre-C++26 semantics (you get UB).
 
That's what I thought as well. I don't see anything in the draft Standard implying programs must write bytes into the storage of erroneous values. The main thing it does is change the required behavior of a buggy program from the UB "anything could happen" to the EB "the behavior is consistent for some specific value of the uninitialized object". It could still have other performance implications since compiler optimization can't assume a used value is not indeterminate.

For this TU below, I see with g++ -O3 and clang++ -O3 that test(false, true) calls f(3). This existing behavior seems like it's also a valid result of EB, though obviously it's not because of a general rule about initializing bytes as "3".

extern void f(int);

// test(false, true) has UB in C++23, EB in C++26
void test(bool a, bool b) {
unsigned char c;
if (a) {
c = 3;
f(1);
}
if (b) {
f(c);
}
}

However, P2795R3 does say "The automatic storage for an automatic variable is always fully initialized, which has potential performance implications. P2723R1 discusses the costs in some detail." And P2723R1 describes performance costs (and gains!) from initializing bytes, and security concerns about leaking data from stack memory via uninitialized objects and padding bytes.

So I'm not sure: Is it the intent or not that typical-architecture code must do extra initialization of some sort for bytes with erroneous value? Does the draft Standard actually say that? It says each erroneous value "is determined by the implementation independently of the state of the program", but that might have an issue in that the Standard normally prescribes the C++ abstract machine ([intro.abstract]), which doesn't have any equivalent of left-over byte values in the stack influenced by previous program execution.

-- Andrew Schepler