Doc. no.: N1857
Date: 2014-07-02
Reply to: Clark Nelson

C++ liaison: DR 455

The requirement

DR 455 is about this requirement, in paragraph 2 of

the default (zero) initialization for objects with static or thread-local storage duration is guaranteed to produce a valid state.

The question in particular is why C++ does not also impose this requirement.

The rationale for omitting the requirement

There is at least one architecture (PA-RISC, which HP apparently stopped supporting in 2013), which has a test-and-clear instruction instead of a test-and-set instruction. That instruction is still a natural way to implement the atomic_test_and_set operation. For that reason, the intent was for the “set” state of an atomic_flag to be representable with an all-zero bit pattern, and the “reset” state to be represented with a non-zero bit-pattern.

There are also architectures on which some data type (especially long long) may be too large to be updateable atomically by the memory system. To accommodate these architectures, the intention was to allow the representation of atomic_long_long (at least) to include an atomic_flag, to be used to prevent contention and word-tearing.

Even if there is no known architecture that has both of these characteristics, it is certainly possible to imagine that there might be one. An implementation of C on such an architecture would have several options; in no particular order, they include:

The last option is worth further comment. It has always been WG14's intention to support architectures where the representation of a null pointer or zero floating-point value is not an all-zero bit-pattern. So theoretically this is just a new application of existing technology.

(I actually have personal experience implementing technology like this. In C++ on Windows, some representations of null pointer-to-member constants require a non-zero bit-pattern. It was inconvenient to have to do this, but not outrageously so. But consider a case of a large statically-allocated array, where the element type is a structure type that includes data of pointer-to-member type, as well as other data that needs to be initialized with an all-zero bit-pattern. I didn't personally need to implement the replication to initialize every member of every element of the array correctly. There are environments in which the replication might significantly inflate the size of an object or executable file. But again, this is just a new instance of an existing problem.)

Considering the list of options as a whole, by omitting this requirement, C++ avoids forcing any implementer to choose among them. Effectively, the requirement is instead placed on the programmer, to do the initialization explicitly. That is consistent with the general philosphy within WG21 that atomic data is an expert-only facility, and shouldn't be made temptingly easy to use. This direction was confirmed when this DR was discussed by SG1 in Rapperswil.

Considerations for WG14

By including this requirement, WG14 does potentially force some unfortunate implementer to choose from among the above alternatives, some of which may be infeasible, and none of which is especially attractive.

It may well be that no real implementer is actually that unfortunate; in any event, the number of such implementers is very likely to be small. Perhaps that reduces the cost of this requirement to an acceptable level.

I don't personally recall the discussion within WG14 that led to adding this requirement. More significantly, I don't recall any WG14 discussion in which all of the above four options were balanced against the benefit of this requirement. This is something that should be discussed.