What Happens to Uninitialized Variables? C++

What happens to uninitialized variables in C/C++?

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 will 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, 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, undefined 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!)

What happens to a declared, uninitialized variable in C? Does it have a value?

Static variables (file scope and function static) are initialized to zero:

int x; // zero
int y = 0; // also zero

void foo() {
static int x; // also zero
}

Non-static variables (local variables) are indeterminate. Reading them prior to assigning a value results in undefined behavior.

void foo() {
int x;
printf("%d", x); // the compiler is free to crash here
}

In practice, they tend to just have some nonsensical value in there initially - some compilers may even put in specific, fixed values to make it obvious when looking in a debugger - but strictly speaking, the compiler is free to do anything from crashing to summoning demons through your nasal passages.

As for why it's undefined behavior instead of simply "undefined/arbitrary value", there are a number of CPU architectures that have additional flag bits in their representation for various types. A modern example would be the Itanium, which has a "Not a Thing" bit in its registers; of course, the C standard drafters were considering some older architectures.

Attempting to work with a value with these flag bits set can result in a CPU exception in an operation that really shouldn't fail (eg, integer addition, or assigning to another variable). And if you go and leave a variable uninitialized, the compiler might pick up some random garbage with these flag bits set - meaning touching that uninitialized variable may be deadly.

What happens to uninitialized variables? C++

The default behavior of an uninitialized function scope (i.e., local) integer in C++ is for it to be indeterminate, which is fine; however if that value is used before it is defined it introduces undefined behavior, and anything could happen - demons could fly out of your nose.

This page on cppreference provides examples of default integer behavior.

On the other hand, all non-local, thread-local variables, not just integers, are zero initialized. But this case wasn't included in your original example.

(Side note: It is generally considered good practice to simply initialize variables anyway and avoid potential hazards altogether... Especially in the form of global variables. )

There are exceptions to best practice using global variables in rare special cases, such as some embedded systems; which initialize values based off of sensor readings on startup, or during their initial loop iteration... And need to retain a value after the scope of their loop ends.

What will be the value of uninitialized variable?

Technically, the value of an uninitialized non static local variable is Indeterminate[Ref 1].

In short it can be anything. Accessing such a uninitialized variable leads to an Undefined Behavior.[Ref 2]

[Ref 1]
C99 section 6.7.8 Initialization:

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

[Ref 2]

C99 section 3.18 Undefined behavior:

behavior, upon use of a nonportable or erroneous program construct, of erroneous data, or of indeterminately valued objects, for which this International Standard imposes no requirements.

Note: Emphasis mine.

What are the dangers of uninitialised variables?

These variables could contain any value if you don't initialize them and reading them in an uninitialized stated is undefined behavior. (except if they are zero initalized)

And if you forgot to initialize one of them, and reading from it by accident results in the value you expect it should have on your current system configuration (due to undefined behavior), then your program might behave unpredictable/unexpected after a system update, on a different system or when you do changes in your code.

And these kinds of errors are hard to debug. So even if you set them at runtime it is suggested to initialize them to known values so that you have a controlled environment with predictable behavior.

There are a few exceptions, e.g. if you set the variable right after you declared it and you can't set it directly, like if you set its value using a streaming operator.

Why can we use uninitialized variables in C++?

C++ gives you the ability to shoot yourself in the foot.

Initialising an integral type variable to 0 is a machine instruction typically of the form

REG XOR REG

Its presence is less than satisfactory if you want to initialise it to something else. That's abhorrent to a language that prides itself on being the fastest. Your assertion that integers are initialised to zero is not correct.

The behaviour of using an uninitialised variable in C++ is undefined.

How does C compilers handle using an uninitialized variable?

This is nothing to do with your compiler, although different compilers may have side-effects that affect the value in a way that appears to be consistent. But regardless, your program has undefined behavior. You did not initialize the value, and so your program's behavior cannot be predicted.

When you declare the variable x, the compiler only records your intent to store a value large enough to hold int. Now, it doesn't matter where it decides to put this. It might push it onto your stack in memory, or it might choose to keep a CPU register available without using memory at all.

So, when you ask for the value of x, there is absolutely no way to know what you will get. Most likely you will get whatever dirty value existed previously at whatever location the compiler determined it would set aside. But equally, the compiler could have utterly failed to even decide where x lives, since it was never used, and then do something awful that leads to a program crash, or just about anything else.

The good news is that you don't have to care about what could happen or why or under what conditions. As a programmer, all you need to care about is that the behavior is undefined. End of story.

And how to fix this? Easy. Give x a value before you ever try to read its value.



Related Topics



Leave a reply



Submit