practice
MOST DEVELOPERS UNDERSTAND that reading
uninitialized variables in C is a defect, but some
do it anyway—for example, to create entropy. What
happens when you read uninitialized objects is
unsettled in the current version of the C standard
(C11).
3 Various proposals have been made to
resolve these issues in the planned C2X revision of
the standard. Consequently, this is a good time to
understand existing behaviors as well as proposed
revisions to the standard to influence the evolution
of the C language. Given the behavior of uninitialized
reads is unsettled in C11, prudence dictates
eliminating uninitialized reads from your code.
This article describes object initialization,
indeterminate values, and trap representations and
then examines sample programs that illustrate the
effects of these concepts on program behavior.
Initialization
Understanding how and when an object is initialized is necessary to understand the behavior of reading an uninitialized object.
An object whose identifier is declared with no linkage (a file scope
object has internal linkage by default)
and without the storage-class specifier
static has automatic storage duration.
The initial value of the object is
indeterminate. If an initialization is specified for the object, it is performed each
time the declaration or compound literal is reached in the execution of the
block; otherwise, the value becomes indeterminate each time the declaration
is reached.
Subsection 6. 7. 9 paragraph 10 of
the C11 Standard4 describes how ob-
jects having static or thread storage du-
ration are initialized:
If an object that has automatic stor-
age duration is not initialized explicitly,
its value is indeterminate. If an object
that has static or thread storage dura-
tion is not initialized explicitly, then:
˲ if it has pointer type, it is initialized
to a null pointer;
˲ if it has arithmetic type, it is initialized to (positive or unsigned) zero;
˲ if it is an aggregate, every member
is initialized (recursively) according to
these rules, and any padding is initialized to zero bits;
˲ if it is a union, the first named
member is initialized (recursively) according to these rules, and any padding is initialized to zero bits.
Many of the dynamic allocation
functions do not initialize memory.
For example, the malloc function allocates space for an object whose size
is specified by its argument and whose
value is indeterminate. For the real-loc function, any bytes in the new object beyond the size of the old object
have indeterminate values.
Indeterminate Values
In all cases, an uninitialized object has
an indeterminate value. The C standard states that an indeterminate value
can be either an unspecified value or
Uninitialized
Reads
DOI: 10.1145/3024920
Article development led by
queue.acm.org
Understanding the proposed revisions
to the C language.
BY ROBERT C. SEACORD