Search

1.6 — Uninitialized variables and undefined behavior

Uninitialized variables

Unlike some programming languages, C/C++ does not initialize most variables to a given value (such as zero) automatically. Thus when a variable is assigned a memory location by the compiler, the default value of that variable is whatever (garbage) value happens to already be in that memory location! A variable that has not been given a known value (usually through initialization or assignment) is called an uninitialized variable.

Author's note

Many readers expect the terms “initialized” and “uninitialized” to be opposites, but they aren’t quite! Initialization means the object was provided with an initial value at the point of definition. Uninitialized means the object has not been given a known value (through any means). Therefore, an object that is assigned a value is no longer uninitialized (because it has been given a known value), even if it wasn’t initialized in the first place.

As an aside...

This lack of initialization is a performance optimization inherited from C, back when computers were slow. Imagine a case where you were going to read in 100,000 values from a file. In such case, you might create 100,000 variables, then fill them with data from the file.

If C++ initialized all of those variables with default values upon creation, this would result in 100,000 initializations (which would be slow), and for little benefit (since you’re overwriting those values anyway).

For now, you should always initialize your variables because the cost of doing so is miniscule compared to the benefit. Once you are more comfortable with the language, there may be certain cases where you omit the initialization for optimization purposes. But this should always be done selectively and intentionally.

Using the values of uninitialized variables can lead to unexpected results. Consider the following short program:

In this case, the computer will assign some unused memory to x. It will then send the value residing in that memory location to std::cout, which will print the value (interpreted as an integer). But what value will it print? The answer is “who knows!”, and the answer may (or may not) change every time you run the program. When the author ran this program in Visual Studio, std::cout printed the value 7177728 one time, and 5277592 the next. Feel free to compile and run the program yourself (your computer won’t explode).

As an aside...

Some compilers, such as Visual Studio, will initialize the contents of memory to some preset value when you’re using a debug build configuration. This will not happen when using a release build configuration. Therefore, if you want to run the above program yourself, make sure you’re using a release build configuration (see lesson 0.9 -- Configuring your compiler: Build configurations for a reminder on how to do that). For example, if you run the above program in a Visual Studio debug configuration, it will consistently print -858993460, because that’s the value (interpreted as an integer) that Visual Studio initializes memory with in debug configurations.

Most modern compilers will attempt to detect if a variable is being used without being given a value. If they are able to detect this, they will generally issue a compile-time error. For example, compiling the above program on Visual Studio produced the following warning:

c:\VCprojects\test\test.cpp(11) : warning C4700: uninitialized local variable 'x' used

If your compiler won’t let you compile and run the above program for this reason, here is a possible solution to get around this issue:

Using uninitialized variables is one of the most common mistakes that novice programmers make, and unfortunately, it can also be one of the most challenging to debug (because the program may run fine anyway if the uninitialized value happened to get assigned to a spot of memory that had a reasonable value in it, like 0).

This is the primary reason for the “always initialize your variables” best practice.

Undefined behavior

Using the value from an uninitialized variable is our first example of undefined behavior. Undefined behavior is the result of executing code whose behavior is not well defined by the C++ language. In this case, the C++ language doesn’t have any rules determining what happens if you use the value of a variable that has not been given a known value. Consequently, if you actually do this, undefined behavior will result.

Code implementing undefined behavior may exhibit any of the following symptoms:

  • Your program produces different results every time it is run.
  • Your program consistently produces the same incorrect result.
  • Your program behaves inconsistently (sometimes produces the correct result, sometimes not).
  • Your program seems like its working but produces incorrect results later in the program.
  • Your program crashes, either immediately or later.
  • Your program works on some compilers but not others.
  • Your program works until you change some other seemingly unrelated code.

Or, your code may actually produce the correct behavior anyway. The nature of undefined behavior is that you never quite know what you’re going to get, whether you’ll get it every time, and whether that behavior will change when you make other changes.

C++ contains many cases that can result in undefined behavior if you’re not careful. We’ll point these out in future lessons whenever we encounter them. Take note of where these cases are and make sure you avoid them.

Rule

Take care to avoid all situations that result in undefined behavior, such as using uninitialized variables.

Author's note

One of the most common types of comment we get from readers says, “You said I couldn’t do X, but I did it anyway and my program works! Why?”.

There are two common answers. The most common answer is that your program is actually exhibiting undefined behavior, but that undefined behavior just happens to be producing the result you wanted anyway… for now. Tomorrow (or on another compiler or machine) it might not.

Alternatively, sometimes compiler authors take liberties with the language requirements when those requirements may be more restrictive than needed. For example, the standard may say, “you must do X before Y”, but a compiler author may feel that’s unnecessary, and make Y work even if you don’t do X first. This shouldn’t affect the operation of correctly written programs, but may cause incorrectly written programs to work anyway. So an alternate answer to the above question is that your compiler may simply be not following the standard! It happens. You can avoid much of this by making sure you’ve turned compiler extensions off, as described in lesson 0.10 -- Configuring your compiler: Compiler extensions.

Quiz time

Question #1

What is an uninitialized variable? Why should you avoid using them?

Show Solution

Question #2

What is undefined behavior, and what can happen if you do something that exhibits undefined behavior?

Show Solution


1.7 -- Keywords and naming identifiers
Index
1.5 -- Introduction to iostream: cout, cin, and endl

22 comments to 1.6 — Uninitialized variables and undefined behavior

  • Vulryn

    I am using do nothing version of this code and I kept getting -858993460. So i changed it from debug to release. Now i keep getting 0 instead of random numbers as output. Is this a problem or undefined behavior ? How can i fix it ?

  • Hi Alex!

    Missing "the"
    "determining what happens if you use [the] value of a variable"

  • Rhylee

    "lack of initialization is a performance optimization that was inherited from C, back when computers were slow. Imagine a case where you were going to read in 100,000 values from a file. In such case, you might create 100,000 variables, then fill them with data from the file. If C++ initialized all of those variables with default values upon creation, this would result in 100,000 initialization (which would be slow), and for little benefit (since you’re overwriting those values anyway)"

    Isn't that what we were supposed to do anyway? Initialize all variables? yet you wrote it would be slow?
    Does this mean the less initialization - the better the computer/program will perform.

  • Mabel

    As we have already been through the chapters of Initializing (1.4), is this chapter of "Uninitialized" basically letting us know how important it is for us to initialize each variable?

    • Alex

      The main point is actually to talk about undefined behavior -- which can occur in many ways in C++. Trying to read from an undefined variable is the first case of undefined behavior that new programmers typically encounter, so it makes for a convenient example.

  • Amanda

    "Lack of initialization is a performance optimization. Imagine you needed 10,000 variables. If these variables were initialized by default, all 10,000 would need to be initialized to the default value upon creation." What does that mean exactly? Does it mean the 10,000 variables each have to be initialized?... Because the paragraph below says

    "This might result in slow program start up. If you did not need these variables immediately, you could always initialize them as you need them, spreading the initialization cost out over the running time of your program."
    Im not too sure what it means all together as it says the program may have a slow start up.

  • Chayim Eliazer

    I ran this "uninitialized variable" in Visual Studio 2019 Enterprise and it did not compile it because of error.
    "Severity    Code    Description    Project    File    Line    Suppression State
    Error    MSB6006    "CL.exe" exited with code 2.    ConsoleApplication2    C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets    429"

    Then tried another time and got 2 errors
        Severity    Code    Description    Project    File    Line    Suppression State
    Error    C4700    uninitialized local variable 'x' used    ConsoleApplication2    C:\Users\Chayi\source\repos\ConsoleApplication2\ConsoleApplication2.cpp    11    

    Severity    Code    Description    Project    File    Line    Suppression State
    Error    LNK1257    code generation failed    ConsoleApplication2    C:\Users\Chayi\source\repos\ConsoleApplication2\LINK    1

  • alfonso

    1.6 — Uninitialized variables and undefined behavior

    Question #1

    What is an uninitialized variable?

    Hide Solution
    An uninitialized variable is a variable that has not been given a value by the program (generally through initialization OR ASSIGNMENT).

    BUT

    1.4 — Variable assignment and initialization

    Question #1

    What is the difference between initialization and assignment?

    Hide Solution
    Initialization gives a variable a value AT THE POINT when it is created. Assignment gives a variable a value AT SOME POINT AFTER it is created.

    So, (first) later assignment is still an initialization or not? In other words, initialization is just the process of giving a variable a first value, no matter this happens in its definition sentence or later in another sentence. ??

    • Alex

      No, the first assignment is not an initialization, it's an an assignment.

      * Initialization = providing a value to an object at the point where it is defined
      * Assignment = providing a value to an object at some point beyond the definition
      * Uninitialized = An object that has not been given a known value

      It's a bit confusing because we naturally expect the terms "initialized" and "uninitialized" to be opposites, but they're not! A variable that is assigned a known value is no longer uninitialized, but it may not have ever been initialized. I'll note this in the lesson.

      • alfonso

        I get it now. Thank you!

      • Bella

        How are they technically not opposites though?

        Initialize is basically providing a value for a variable at the same time (After the variable is defined)
        Uninitialized is basically a variable (Object) that hasn't been given a value.

        One is providing value, whilst the other hasn't been given a value.
        Or am I wrong?

        • Alex

          A variable that was not initialized but was later given a value through assignment now has a known value. Thus, it is no longer considered "uninitialized", even though it was assigned a value, not initialized with one.

  • Athena

    code straight up wont run

    Error    C2220    warning treated as error - no 'object' file generated

    Warning    C4100    'x': unreferenced formal parameter

    Edit: If i remove the "x" in "&x" the code now works. not sure if its a typo or just me being stupid and missing something :/

    • Hi!

      Your compiler complains, because @x is never used.

      You can remove the "x", making the parameter anonymous.

      You could add an attribute, indicating that @x is unused on purpose.

      Or you could disable C4100.

      @Alex (Do you get highlights for mentions or do you read everything anyway?)

  • It always returns me the value of 0 when I don't assign a value to x in my IDE.

    • The value is undefined. Changes to your code that seem unrelated could change the number. Changes to you compiler could change the number. Changes to your system could change the number.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]