What happens to uninitialized variables in C/C++?
Asked Answered
A

5

1

From "C++ Primer" by Lippman,

When we define a variable, we should give it an initial value unless we are certain that the initial value will be overwritten before the variable is used for any other purpose. If we cannot guarantee that the variable will be reset before being read, we should initialize it.

  1. What happens if an uninitialized variable is used in say an operation? Will it crash/ will the code fail to compile?

    I searched the internet for answer to the same but there were differing 'claims'. Hence the following questions,

  2. Will C and C++ standards differ in how they treat an uninitialized variable?

  3. Regarding similar queries, how and where can I find an 'official' answer? Is it practical for an amateur to look up the C and C++ standards?

Astor answered 2/1, 2022 at 17:25 Comment(3)
Will it crash? Who knows. Can it crash? Oh most definitely.Jadda
There are many answers to this question on this site. The reason you might see contradicting answers is because some answers are given from the point of view of the C/C++ standards and what they guarantee while other answers are given from the point of view of typical implementations of the languages on current platforms/compilers. You see this in the answers here as well.Willms
The C and C++ standards will differ in details of what happens, but at the end you shouldn't bother with these details. Assume that it is illegal to use the value of uninitialized variables. Also always assume if not stated otherwise, that a C or C++ compiler will not warn about illegal constructs, nor will the program have any defined behavior or crash (aka undefined behavior).Willms
D
7

Q.1) What happens if an uninitialized variable is used in say an operation? Will it crash/ will the code fail to compile?

Many compilers try to warn you about code that improperly uses the value of an uninitialized variable. Many compilers have an option that says "treat warnings as errors". So depending on the compiler you're using and the option flags you invoke it with and how obvious it is that a variable is uninitialized, the code might fail to compile, although we can't say that it will fail to compile.

If the code does compile, and you try to run it, it's obviously impossible to predict what will happen. In most cases the variable will start out containing an "indeterminate" value. Whether that indeterminate value will cause your program to work correctly, or work incorrectly, or crash, is anyone's guess. If the variable is an integer and you try to do some math on it, you'll probably just get a weird answer. But if the variable is a pointer and you try to indirect on it, you're quite likely to get a crash.

It's often said that uninitialized local variables start out containing "random garbage", but that can be misleading, as evidenced by the number of people who post questions here pointing out that, in their program where they tried it, the value wasn't random, but was always 0 or was always the same. So I like to say that uninitialized local variables never start out holding what you expect. If you expected them to be random, you'll find that (at least on any given day) they're repeatable and predictable. But if you expect them to be predictable (and, god help you, if you write code that depends on it), then by jingo, you'll find that they're quite random.

Whether use of an uninitialized variable makes your program formally undefined turns out to be a complicated question. But you might as well assume that it does, because it's a case you want to avoid just as assiduously as you avoid any other dangerous, imperfectly-defined behavior.

See this old question and this other old question for more (much more!) information on the fine distinctions between undefined and indeterminate behavior in this case.

Q.2) Will C and C++ standards differ in how they treat an uninitialized variable?

They might differ. As I alluded to above, and at least in C, it turns out that not all uses of uninitialized local variables are formally undefined. (Some are merely "indeterminate".) But the passages quoted from the C++ standards by other answers here make it sound like it's undefined there all the time. Again, for practical purposes, the question probably doesn't matter, because as I said, you'll want to avoid it no matter what.

Q.3) Regarding similar queries, how and where can I find an 'official' answer? Is it practical for an amateur to look up the C and C++ standards?

It is not always easy to obtain copies of the standards (let alone official ones, which often cost money), and the standards can be difficult to read and to properly interpret, but yes, given effort, anyone can obtain, read, and attempt to answer questions using the standards. You might not always make the correct interpretation the first time (and you may therefore need to ask for help), but I wouldn't say that's a reason not to try. (For one thing, anyone can read any document and end up not making the correct interpretation the first time; this phenomenon is not limited to amateur programmers reading complex language standards documents!)

Demi answered 2/1, 2022 at 17:51 Comment(7)
"But the passages quoted from the C++ standards by other answers here make it sound like it's undefined all the time.": The cited answers conveniently left out following parts detailing the exceptions to the rule. There are exceptions for certain types, e.g. unsigned char, unsigned char and std::byte in certain situations, etc.Willms
"Many compilers will warn you about code that improperly uses the value of an uninitialized variable.": I think it is important that all of these warning options cannot possibly warn on every possible uninitialized use. They only warn about cases in which the uninitialized access is relatively obvious/likely (or maybe warn for every access that is not provably initialized, but that would give many false positives).Willms
@Steve Summit you mentioned the case of uninitialized local variables? What about the global variables? Other answers mentioned, that global variables automatically initialise with value 0? Is that right and if so is that standard defined? Also, am I right to say that indeterminate behaviour is logically possible but the result isn't explicit and undefined behaviour is both illogical and not explicit at the same time?Astor
@Astor Yes, global (and static) variables are guaranteed to be initialized to 0 if you don't explicitly initialize them yourself. See this question for a good summary.Demi
am I right to say that indeterminate behaviour is logically possible but...? I'm not sure that's a useful description. There are a number of different ways that the standard describes something that it doesn't define. You can have behavior that is undefined, or implementation-defined, or unspecified/indeterminate, or locale-specific. These differ in terms of (a) how widely the actual behavior is allowed to vary and (b) how bad it is to write code that depends on it. See this question for more details.Demi
See also question 11.33 in the C FAQ list.Demi
Related: Where do the values of uninitialized variables come from, in practice on real CPUs?Banting
F
3

C++

The C++ Standard, [dcl.init], paragraph 12 [ISO/IEC 14882-2014], states the following:

If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced. If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

(end quote)

So using an uninitialized variable will result in undefined behavior.

Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may give your expected output or it may crash.

C

The C Standard, 6.7.9, paragraph 10, specifies [ISO/IEC 9899:2011]

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.

Uninitialized automatic variables or dynamically allocated memory has indeterminate values, which for objects of some types, can be a trap representation. Reading such trap representations is undefined behavior.


1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.

Fewell answered 2/1, 2022 at 17:38 Comment(2)
There is also a requirement that the uninitialized variable has its address taken in the C standard for value use to be legal, independent of type: port70.net/~nsz/c/c11/n1570.html#6.3.2.1p2Willms
The cases where it's not UB in C++ are very limited, and involve initializing or assigning one unsigned char or std::byte object from another. en.cppreference.com/w/cpp/language/default_initialization. (The current C++ draft standard has the indeterminate value rules in [basic.memobj], not [dcl.init] anymore - eel.is/c++draft/basic#indet)Banting
D
2

What happens if an uninitialized variable is used in say an operation?

It depends. If the operation uses the value of the variable, and the type of the variable and the expression aren't excepted from it, then the behaviour of the program is undefined.

If the value isn't used - such as in the case of sizeof operator, then nothing particular happens that wouldn't happen with an initialised variable.

Will C and C++ standards differ in how they treat an uninitialized variable?

They use different wording, but are essentially quite similar in this regard.

C defines the undefined behaviour of indeterminate values through the concept of "trap representation" and specifies types that are guaranteed to not have trap representations.

C++ doesn't define the concept of "trap representation", but rather lists exceptional cases where producing an indeterminate value doesn't result in undefined behaviour. These cases have some overlap with the exceptional types in C, but aren't exactly the same.

Regarding similar queries, how and where can I find an 'official' answer?

The official answer - if there is one - is always in the language standard document.

Darien answered 2/1, 2022 at 17:31 Comment(1)
There is also a requirement that the uninitialized variable has its address taken in the C standard for value use to be legal, independent of type: port70.net/~nsz/c/c11/n1570.html#6.3.2.1p2Willms
H
1

The standard says it is undefined.

However on a Unix or VMS based system (Gnu/Linux, UNIX, BSD, MS-Windows > XP or NT, MacOS > X) then the stack and heap are initialised to zero (this is done for security reasons. Now to make your code work.)

However if you go up and down the stack or free then malloc then the data will be random rubish. (there may be other causes of random rubish. Don't rely on undefined behaviours).

Could the program crash? (By this, you mean detect error at run-time.)

Probably not, but again this is undefined behaviour. A C interpreter may do this.

Note also, some C++ types have a constructor that does well-defined initialisation.

Helicopter answered 2/1, 2022 at 18:12 Comment(0)
W
0

You have tagged both C and C++. In C, an uninitialized variable probably has junk bits. Often your compiler with put zero bits there, but you can not count on it. So if you use that variable without explicitly initializing, the result may be sensible and it may not. And strictly speaking this is undefined behavior, so anything at all may happen.

C++ has the same for simple variables, but there is an interesting exception: while a int x[3] contains junk, std::vector x(3) contains zeros.

Winery answered 2/1, 2022 at 17:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.