This question already has answers here:
Uninitialized variable behaviour in C++
(4 answers)
Closed 2 years ago.
If I don't initialize a C++ variable, I find that it automatically gives it 0 on some android phones, but not on others, and zero on all IOS phones.
So what determines whether you give it 0, is it the phone system, is it the compiler, is it some compiler option
It is undefined behaviour to read an uninitialized variable. If you do that your program is meaningless and the compiler is no longer required to generate anything sensible for the entire program.
What determines the initial value of C++ variables
If I don't initialize a C++ variable
I assume you refer to automatic storage. Variables in static or thread local storage are zero initialised implicitly.
From perspective of the language: The initial value is simply indeterminate. Whether anything affects this value indirectly is unspecified. The behaviour of reading an indetrminate value is in most cases undefined.
In practice: It is typically determined by whatever happens to be in the memory before it was allocated for the variable.
is it some compiler option
Perhaps, or maybe not. It's impossible to tell without seeing the compiler and options that were used.
I know that people have experimented with a compiler feature that initialises uninitialised variables, but I don't know of an official mainstream compiler release with such option. That doesn't mean it doesn't exist.
C++ variables are not warrantied to be initialized unless you define a constructor for the class of them.
In case of basic types or structs of basic types (aka POD, Plain Old Data) the value will be undefined unless you explicitly assign something to them.
Some compiler initialize them, some do it when you are generating debug information, but it is not a portable nor trusted way to do it.
You should not use uninitialized variables, as such will produce an undefined behavior.
Related
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.
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,
Will C and C++ standards differ in how they treat an uninitialized variable?
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?
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!)
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.
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.
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.
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.
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.
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,
Will C and C++ standards differ in how they treat an uninitialized variable?
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?
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!)
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.
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.
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.
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.
In a program I am writing I currently have several uninitialised variables in my .h files, all of which are initialised at run-time. However, in Visual Studio it warns me every time I do this to "Always initialise a member variable" despite how seemingly pointless it feels to do so. I am well aware that attempting to use a variable when uninitialised will lead to undefined behaviour, but as far as I know, this can be avoided by not doing so. Am I overlooking something?
Thanks.
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.
You have not included the source so we have to guess about why it happens, and I can see possible reasons with different solutions (except just zero-initializing everything):
You don't initialize at the start of the constructor, but you combine member initialization with some other code that calls some functions for the not fully initialized object. That's a mess - and you never know when some functions will call another function using some non-initialized member. If you really need this, don't send in the entire object - but only the parts you need (might need more refactoring).
You have the initialization in an Init-function. Just use the recent C++-feature of having one constructor call another instead.
You don't initialize some members in the constructor, but even later. If you really don't want to initialize it having a pointer (or std::unique_ptr) containing that data, and create it when needed; or don't have it in the object.
It's a safety measure to not allow uninitialized variables, witch is a good thing, but if you are sure of what you are doing and you make sure your variables are always initialzed before use, you can turn this off, right click on your project in solution explorer -> properties -> C/C++ -> SDL checks, this should be marked as NO. It comes as YES by default.
Note that these compile-time checks do more than just check for unitialized variables, so before you turn this off I advise reading https://learn.microsoft.com/en-us/cpp/build/reference/sdl-enable-additional-security-checks?view=vs-2019
You can also disable a specific warning in you code using warning pragma
Personally I keep these on because IMO in the tradeoff safety/annoyance I prefer safety, but I reckon that someone else can have a different opinion.
There are two parts to this question: first is reading uninitialized variables dangerous and second is defining variables uninitialized dangerous even if I make sure I never access uninitialized variables.
What are the dangers of accessing uninitialized variables?
With very few exceptions, accessing an uninitialized variable makes the whole program have Undefined Behavior. There is a common misconception (which unfortunately is taught) that uninitialized variables have "garbage values" and so reading an uninitialized variable will result in reading some value. This is completely false. Undefined Behavior means the program can have any behavior: it can crash, it can behave as the variable has some value, it can pretend the variable doesn't even exist or all sorts of weird behaviors.
For instance:
void foo();
void bar();
void test(bool cond)
{
int a; // uninitialized
if (cond)
{
a = 24;
}
if (a == 24)
{
foo();
}
else
{
bar();
}
}
What is the result of calling the above function with true? What about with false?
test(true) will cleary call foo().
What about test(false)? If you answer: "Well it depends on what garbage value is in variable a, if it is 24 it will call foo, else it will call bar" Then you are completely wrong.
If you call test(false) the program accesses an uninitialized variable and has Undefined Behavior, it is an illegal path and so the compilers are free to assume cond is never false (because otherwise the program would be illegal). And surprise surprise both gcc and clang with optimizations enabled actually do this and generate this assembly for the function:
test(bool):
jmp foo()
So don't do this! Never access uninitialized variable! It is undefined behavior and it's much much worse than "the variable has some garbage value". Furthermore, on your system could work as you expect, on other systems or with other compiler flags it can behave in unexpected ways.
What are the dangers of defining uninitialized variables if I make sure I always initialize them later, before accessing them?
Well, the program is correct from this respect, but the source code is prone to errors. You have to mentally burden yourself with always checking if somewhere you actually initialized the variable. And if you did forget to initialize a variable finding the bug will be difficult as you have a lot of variables in your code who are defined uninitialized.
As opposed, if you always initialize your variables you and the programmers after you have a much much easier job and ease of mind.
It's just a very very good practice.
I know that local variables in C & C++ aren't automatically initialized & if no initial value is given to them they have garbage values. I also know that global & static variables are by default initialized to zero. Use of uninitialized variable results in undefined behavior in C++.
But recently I tried following simple C++ program on various implementations of C++ & all gives me 0 as output.
#include <iostream>
int main()
{
int u;
std::cout<<u<<'\n';
}
Output:
CodeBlocks 13.12 IDE: 0
Orwell Dev C++ 5.8.3: 0
Ideone.com: 0 (visit this: http://ideone.com/zWrgwo)
Is it true that modern compilers automatically initializes local variables to 0? or such type of program still represents undefined behavior ? Is it guaranteed to see 0 as output on every modern implementation of C++ always?
Specific implementations are free to not set them ("local" variables) to anything, or to set them to any value they want, including zero. The standard doesn't mandate they they be set to a non-zero value, after all :-)
The standard merely states that their value, if not explicitly set, is undefined. Hence it's not something a good programmer would rely upon. This is covered in C++11 8.5 Initializers [dcl.init] /11 (my emphasis):
If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value.
So, in answer to your closing question, is it guaranteed to see 0 as output on every modern implementation of C++ always?, the answer is no, plain and simple.
As an aside, you may well find that the three "separate" environments you tested on, CodeBlocks, DevC++ and ideone, are all using the same compiler under the covers, so it would hardly be an exhaustive test in that case.
No it is not true. Initialising variables to zero would incur an unnecessary performance cost. Non-static variables are not initialised to zero.
The behaviour of using an uninitialised variable in C++ is undefined.
You might find that a debug configuration zero-initialises variables. I find that particularly pernicious and always ensure that any compiler options doing that are switched off.
Recent Windows versions (and maybe other OS too) initialize all uninitialized memory to 0 when a program is starting.
Therefore all "uninitialized" variables will appear as 0.
However this depends on the OS, not on the compiler. When running such a program under Windows 9x (which did not have this feature) the variables have random values.
Variables on the stack will contain random values as soon as the stack has been used:
void test()
{
int a;
std::cout << a;
}
int main()
{
someLargeFunction();
test();
}
The value of the variable "a" is now depending on the function "someLargeFunction"!
In my class I was using such field:
private:
bool firstSeqNumReceived;
Everything were working fine for a while but after one commit I've figured out that now field is true by default. Surprisingly field is not initialized to false by default, instead assigned value is implementation dependent (refer to What is the default value for C++ class members for more details )
Now I wonder why compiler doesn't produce compile-time error forcing me to add initialization?
Who needs "implementation-dependent" default value, are there any use-cases? Why not produce compile-time error in this case?
I wonder why compiler doesn't produce compile-time error forcing me
to add initialization?
Because the compiler assumes you know what you're doing.
In C++ you don't pay for what you don't use. There may be use cases where initialization is a waste of time. For example, in a class where real meaningful values for members cannot possibly be computed until after the object has been constructed, initializing the members to some default or sentinel value accomplishes little.
The use-case is basically, that it depends on the program flow if you are using the variable or not. If you don't use it in parts of your code then there is also no need to zero initialise it.
Also if you know, that the value will be assigned in the constructor or some other member function it would be just a superfluous step to first write 0 into memory.
The standard specifies that it is undefined behaviour to access an uninitialized object. There are a few reasons such undefined behaviour appears in the standard. This one is more about not giving you more than you ask for. Sometimes you really don't want to initialize a variable as soon as you create it. Instead, the compiler trusts you to initialize an object when you need it initialized. As an example of when you don't want it initialized automatically:
int x;
std::cin >> x;
It would be completely pointless to automatically initialize x to 0 as the value is immediately overwritten. The power to initialize a variable is in your capable hands.
Compilers may also assume you do not invoke undefined behaviour in order to make optimizations.