This question already has answers here:
(Why) is using an uninitialized variable undefined behavior?
(7 answers)
Closed 5 years ago.
Possible Duplicate:
Is uninitialized data behavior well specified?
I tried the following code
#include<stdio.h>
void main()
{
int i; \
printf('%d',i);
}
The result gave garbage value in VC++, while same in tc was zero.
What will be the correct value?
Will an uninitialized variable by default have value of zero? or it will contain garbage value?
Next is on the same
#include<stdio.h>
void main()
{
int i,j,num;
j=(num>0?0:num*num);
printf("\n%d",j);
}
What will be the output of the code above?
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.
Accessing an unitialized variable is undefined behavior in both C and C++, so reading any value is possible.
It is also possible that your program crashes: once you get into undefined behavior territory, all bets are off1.
1 I have never seen a program crashing over accessing an uninitalized variable, unless it's a pointer.
It's indeterminate. The compiler can do what it wants.
The value is indeterminate; using the variable before initialization results in undefined behavior.
It's undefined. It might be different between different compilers, different operating systems, different runs of the program, anything. It might not even be a particular value: the compiler is allowed to do whatever it likes to this code, because the effect isn't defined. It might choose to optimize away your whole program. It might even choose to replace your program with one that installers a keylogger and steals all of your online banking login details.
If you want to know the value, the only way is to set it.
As others have noted, the value can be anything.
This sometimes leads to hard-to-find bugs, e.g. because you happen to get one value in a debug build and get a different value in a release build, or the initial value that you get depends on previous program execution.
Lesson: ALWAYS initialize variables. There's a reason that C# defines values for fields and requires initialization for local variables.
Related
const int a = 100;
int *p = &a;
*p = 99;
printf("value %d", a);
Above code compiles and I am able to update its value via pointer but code below didn't output anything.
static const int a = 100;
int *p = &a;
*p = 99;
printf("value %d", a);
Can anyone explain this thing.
Both code snippets are invalid C. During initialization/assignment, there's a requirement that "the type pointed to by the left has all the qualifiers of the type pointed to
by the right" (c17 6.5.16.1). This means we can't assign a const int* to an int*.
"Above code compiles" Well, it doesn't - it does not compile cleanly. See What must a C compiler do when it finds an error?.
I would recommend you to block invalid C from compiling without errors by using (on gcc, clang, icc) -std=c11 -pedantic-errors.
Since the code is invalid C, it's undefined behavior and why it has a certain behavior is anyone's guess. Speculating about why you get one particular output from one case of undefined behavior to another isn't very meaningful. What is undefined behavior and how does it work? Instead focus on writing valid C code without bugs.
There are several things going on here:
const does not mean "Put this variable in read-only memory or otherwise guarantee that any attempt to modify it will definitively result in an error message."
What const does mean is "I promise not to try to modify this variable." (But you broke that promise in both code fragments.)
Attempting to modify a const-qualified variable (i.e., breaking your promise) yields undefined behavior, which means that anything can happen, meaning that it might do what you want, or it might give you an error, or it might do what you don't want, or it might do something totally different.
Compilers don't always complain about const violations. (Though a good compiler should really have complained about the ones here.)
Some compilers are selective in their complaints. Sometimes you have to ask the compiler to warn about iffy things you've done.
Some programmers are careless about ignoring warnings. Did your compiler give you any warnings when you compiled this?
The compiler should complain in both cases when you store the address of a const int into p, a pointer to modifiable int.
In the first snippet, a is defined as a local variable with automatic storage: although you define it as const, the processor does not prevent storing a value into it via a pointer. The behavior is undefined, but consistent with your expectations (a is assigned the value 99 and this value is printed, but the compiler could have assumed that the value of a cannot be changed, hence could have passed 100 directly to printf without reading the value of a).
In the second snippet, a is a global variable only accessible from within the current scope, but the compiler can place it in a read-only location, causing undefined behavior when you attempt to modify its value via the pointer. The program may terminate before evaluating the printf() statement. This is consistent with your observations.
Briefly, modifying const-qualified static objects causes a trap and modifying a const-qualified automatic object does not because programs are able to place static objects in protected memory but automatic objects must be kept in writeable memory.
In common C implementations, a const-qualified static object is placed in a section of the program data that is marked read-only after it is loaded into memory. Attempting to modify this memory causes the processor to execute a trap, which results in the operating system terminating execution of the program.
In contrast, an object with automatic storage duration (one defined inside a function without static or other storage duration) cannot easily be put in a read-only program section. This is because automatic objects need to be allocated, initialized, and released during program execution, as the functions they are defined in are called and returned. So even though the object may be defined as const for the purposes of the C code, the program needs to be able to modify the memory actually used for it.
To achieve this, common C implementations put automatic objects on the hardware stack, and no attempt is made to mark the memory read-only. Then, if the program mistakenly attempts to modify a const-qualified automatic object, the hardware does not prevent it.
The C standard requires that the compiler issue a diagnostic message for the statement int *p = &a;, since it attempts to initialize a pointer to non-const with the address of a const-qualified type. When you ignore that message and execute the program anyway, the behavior is not defined by the C standard.
Also see this answer for explanation of why the program may behave as though a is not changed even after *p = 99; executes without trapping.
6.7.3 Type qualifiers
...
6 If an attempt is made to modify an object defined with a const-qualified type through use
of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is
made to refer to an object defined with a volatile-qualified type through use of an lvalue
with non-volatile-qualified type, the behavior is undefined.133)
133) This applies to those objects that behave as if they were defined with qualified types, even if they are
never actually defined as objects in the program (such as an object at a memory-mapped input/output
address).
C 2011 Online Draft
If you declare a as const, you're making a promise to the compiler that the value of a should not change during its lifetime; if you try to assign a new value to a directly the compiler should at least issue a diagnostic. However, by trying to change a through a non-const pointer p you're breaking that promise, but you're doing it in such a way that the compiler can't necessarily detect it.
The resulting behavior is undefined - neither the compiler nor the runtime environment are required to handle the situation in any particular way. The code may work as expected, it may crash outright, it may appear to do nothing, it may corrupt other data. const-ness may be handled in different ways depending on the compiler, the platform, and the code.
The use of static changes how a is stored, and the interaction of static and const is likely what's leading to the different behavior. The static version of a is likely being stored in a different memory segment which may be read-only.
Why am i getting 0. I is an auto variable, so it should print some garbage value, right? I am using gcc compiler.
#include "stdio.h"
void main() {
int i;
printf("%d\n", i);
}
Does gcc initializes auto variable to 0?
Yes and No!
Actually uninitialized auto variables get indeterminate value (either an unspecified value or a trap representation1).
Using such variables in a program invoke undefined behavior-- behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
for which ANSI C International Standard imposes no requirements. (C11:§3.4.3)
Once UB is invoked you may get either expected or unexpected result. Result may vary run to run of that program, compiler to compiler or even version to version of same compiler, even on temperature of your system!
1. An automatic variable can be initialized to a trap representation without causing undefined behavior, but the value of the variable cannot be used until a proper value is stored in it. (C11: 6.2.6 Representations of types--Footnote 50)
No, I get random values with gcc (Debian 4.9.2-10) 4.9.2.
ofd#ofd-pc:~$ gcc '/home/ofd/Destkop/test.c'
ofd#ofd-pc:~$ '/home/ofd/Desktop/a.out'
-1218415715
ofd#ofd-pc:~$ '/home/ofd/Desktop/a.out'
-1218653283
ofd#ofd-pc:~$ '/home/ofd/Desktop/a.out'
-1218845795
Variables declared inside a function are uninitialized. One cannot predict what might show up if you print them out. in your example main is a function too. Hence it so happens that it is zero.
When you declare variable to be static or gloabally, the compiler will have them initialzed to zero.
It has become standard security practice for freshly allocated memory to be cleared (usually to 0) before being handed over by the OS. Don't want to be handing over memory that may have contained a password or private key! So, there's no guarantee what you'll get since the compiler is not guaranteeing to initialize it either, but in modern days it will typically be a value that's consistent across a particular OS at least.
This question already has answers here:
Checking return value of a function without return statement
(3 answers)
Closed 8 years ago.
So, I did some changes in this simple program for understanding purposes.
Here is the code:
#include<stdio.h>
add1(int a,int b){
int j = a + b; // Statement-1
int y = a - b; // Statement-2
}
void main() {
int result = add1(5,7);
printf("%d",result);
}
I know that the default return type of a C function is int and the default return value is return 0 if the function is main, else the return value is undefined if the function does return something. I know that it is not a good practice. But here are my observations:
The return value of add1 takes the value of the closest declared variable to the ending brace of the add1 function i.e in my code y. Hence, the output is -2. If I comment the statement-2 the output becomes 12.
So, is this what we call undefined behavior?
Yes. Once there is undefined behavior, result may comes out to be either expected or unexpected.
C faq - 11.33:
undefined: Anything at all can happen; the Standard imposes no requirements. The program may fail to compile, or it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.
C faq - 11.35:
A compiler may do anything it likes when faced with undefined behavior (and, within limits, with implementation-defined and unspecified behavior), including doing what you expect. It's unwise to depend on it, though.
Yes. §6.9.1 ¶12 of N1256 (C99) states:
If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
It appears that you are saying that your compiler appears to return the value of the last defined variable and are wondering whether that particular algorithm is what is meant by "undefined behavior." Actually the algorithm that a particular compiler uses, if any, to set a return value, in a way, doesn't really demonstrate notion of undefined behavior.
The right way to look at things is that the language specification allows a (conforming) compiler to generate code that does whatever it wants to set a return value (or crash or go into an infinite loop).
The fact that you appeared to have found that your compiler does some particular thing is actually somewhat irrelevant. It didn't have to do what you found it to do. It could have done something else.
Not that anyone asked, but what you are seeing is probably a result of what generally happens in C compilers: the value returned from a function is the value that happens to be held in a particular processor register when the function exits. It appears your compiler is targeting its computations directly into that special register. So yeah, the fact that you are seeing what you are seeing makes sense (at least to compiler writers).
But it doesn't have to be that way. The fact that it is that way simply agrees with the language requirement of undefined behavior, but it is not "what is meant by" undefined behavior.
Maybe this is just a nit-pick, but it reflects how I read the question.
I have a great difficulty in understanding the printed values of these 2 source codes.
#include<stdio.h>
void a(void){
int a;
a++;
printf("%d\n",a);
}
int main(void){
a();
a();
a();
return 0;
}
Why does this code print out "1 2 3 " ,while the second one:
#include<stdio.h>
void a(void){
int a;
a++;
printf("%d\n",a);
}
int main(void){
int b;
printf("%d\n",b);
a();
a();
a();
return 0;
}
Prints out: " 0, garbage value, same garbage value +1, same garbage value +2 ".
Shouldn't any uninitialized object in the main function (or any other functon ) be assigned a random (garbage) value?
UPDATE: I feel that the explanation "the variables are uninitialized so they can have any remaining values from other programs so -> UB" is not sufficient. I can copy-paste the same source code 100 times and still get the printed value of 0. I am using gcc 4.4.3.
The value of uninitialized automatic variables is indeterminate and so if you don't talk about a specific compiler on a specific machine with a specific set of flags then it is really unpredictable. Even if you talk about a very specific platform and settings you still may not get reproducible results.
In some very specific situations you can make predictions and the presentation Deep C talks about this in general and covers this specific case around slide 71.
On modern systems automatic variables will often be allocated on the stack and you may get the same memory location and therefore you would then see three consecutive values. But you should not rely on this behavior and using uninitialized variables is undefined behavior and the results are unpredictable.
The C99 draft standard tell us in section 6.7.8 Initialization paragraph 10 that:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
and tell us in the definitions of indeterminate value:
either an unspecified value or a trap representation
Update
What is undefined behavior? In the strictest sense it is behavior the C standard does not impose requirements on, it is construct of the standard. It is defined in the draft standard in section 3.4.3:
behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
for which this International Standard imposes no requirements
and has the following note:
Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
at the end of the day it is a trade off between designing an efficient language and a safe one, which is paraphrased from What Every C Programmer Should Know About Undefined Behavior #1/3.
Here are more links to better understanding undefined behavior:
Philosophy behind Undefined Behavior
Why Language Designers Tolerate Undefined Behavior
int a; In first code you haven't initialized a which means it contains garbage values in it. Both the above codes snippets could behave differently printing garbage values.
An uninitialized variable is a variable that is declared but is not set to a definite known value before it is used. It will have some value, but not a predictable one. As such, it is a programming error and a common source of bugs in software.
Since all values are uninitialized they could contain anything.
So your output is unpredictable because you cannot know what value the variables have.
This is what is called undefined behavior.
Why does this code print out "1 2 3 "
It invokes undefined behavior. Any thing could happen. Using an uninitialized variable invokes UB.
Shouldn't any uninitialized object in the main function (or any other functon ) be assigned a random (garbage) value?
Yes. But that garbage value could be any thing. you can't predict it.
It's both undefined bahaviour. It just happens to be 0 for the local variable in main and also 0 for the local variable in the first example. And then a random value at the shifted local variable location for a in the second example (shifted due to a local variable in main).
Memory pages are usually zero'd when retrieved from the OS, so it's most likely the stack footprint of the language runtime or some other pre-main code. Therefore being seemingly predictable for you at repeated runs. It's possibly completely different on different machines/compilers etc.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
e.g. I'm usually compulsive obsessive and like to do
static int i = 0;
if (!i) i = var;
but
static int i;
if (!i) i = var;
would also work.
Why? Why can't it segfault so we can all be happy that undefined variables are evil and be concise about it?
Not even the compilers complain:(
This 'philosophy' of indecisiveness in C has made me do errors such as this:
strcat(<uninitialized>, <proper_string>)) //wrong!!1
strcpy(<uninitialized>, <proper_string>)) //nice
In your example, i is not an undefined variable, it is an uninitialized variable. And C has good reasons for not producing an error in these cases. For instance, a variable may be uninitialized when it is defined but assigned a value before it is used, so it is not a semantic error to lack an initialization in the definition statement.
Not all uses of uninitialized variables can be checked at compile-time. You could suggest that the program check every access to every variable by performing a runtime check, but that requires incurring a runtime overhead for something that is not necessary if the programmer wrote the code correctly. That's against the philosophy of C. A similar argument applies to why automatically-allocated variables aren't initialized by default.
However, in cases where the use of a variable before being initialized can be detected at compile-time, most modern compilers will emit a warning about it, if you have your warning level turned up high enough (which you always should). So even though the standard does not require it, it's easy to get a helpful diagnostic about this sort of thing.
Edit: Your edit to your question makes it make no sense. If i is declared to be static then it is initialized -- to zero.
This comes from C's "lightweight" and "concise" roots. Default initializing to zero bytes was free (for global variables). And why specify anything in source text when you know what the compiler is going to do?
Uninitialized auto variables can contain random data, and in that case your "if" statements are not only odd but don't reliably do what you desire.
It seems you don't understand something about C.
int i;
actually DOES define the variable in addition to declaring it. There is memory storage. There is just no initialization when in function scope.
int i=0;
declares, defines, and initializes the storage to 0.
if (!i)
is completely unnecessary before assigning a value to i. All it does is test the value of integer i (which may or may not be initialized to a specific value depending on which statement above you used).
It would only be useful if you did:
int *i = malloc(sizeof int);
because then i would be a pointer you are checking for validity.
You said:
Why? Why can't it segfault so we can all be happy that undefined variables are evil and be concise about it?
A "segfault" or segmentation fault, is a term that is a throwback to segmented memory OSes. Segmentation was used to get around the fact that the size of the machine word was inadequate to address all of available memory. As such, it is a runtime error, not a compile time one.
C is really not that many steps up from assembly language. It just does what you tell it to do. When you define your int, a machine word's worth of memory is allocated. Period. That memory is in a particular state at runtime, whether you initialize it specifically or leave it to randomness.
It's to squeeze every last cycle out of your CPU. On a modern CPU of course not initializing a variable until the last millisecond is a totally trivial thing, but when C was designed, that was not necessarily the case.
That behavior is undefined. Stack variables are uninitialized, so your second example may work in your compiler on your platform that one time you ran it, but it probably won't in most cases.
Getting to your broader question, compile with -Wall and -pedantic and it may make you happier. Also, if you're going to be ocd about it, you may as well write if (i == 0) i = var;
p.s. Don't be ocd about it. Trust that variable initialization works or don't use it. With C99 you can declare your variables right before you use them.
C simply gives you space, but it doesn't promise to know what is in that space. It is garbage data. An automatically added check in the compiler is possible, but that extends compile times. C is a powerful language, and as such you have the power to do anything and fall on your face at the same time. If you want something, you have to explicitly ask for it. Thus is the C philosophy.
Where is var defined?
The codepad compiler for C gives me the following error:
In function 'main': Line 4: error:
'var' undeclared (first use in this
function) Line 4: error: (Each
undeclared identifier is reported only
once Line 4: error: for each function
it appears in.)
for the code:
int main(void)
{
static int i;
if (!i) i = var;
return 0;
}
If I define var as an int then the program compiles fine.
I am not really sure where your problem is. The program seems to be working fine. Segfault is not for causing your program to crash because you coded something that may be undefined in the language. The variable i is unitialized not undefined. You defined it as static int. Had you simply done:
int main(void)
{
i = var;
return 0;
}
Then it would most definately be undefined.
Your compiler should be throwing a warning because i isn't initialized to catch these sort of gotchas. It seems your if statement is sort of a catch for that warning, even if the compiler does not report it.
Static variables (in function or file scope) and global variables are always initialized to zero.
Stack variables have no dependable value. To answer your question, uninitialized stack variables are often set to non-zero, so they often evaluate as true. That cannot be depended on.
When I was running Gentoo Linux I once found a bug in some open source Unicode handling code that checked an uninitialized variable against -1 in a while loop. On 32-bit x86 with GCC this code always ran fine, because the variable was never -1. On AMD-64 with its extra registers, the variable ended up always set to -1 and the processing loop never ran.
So, always use the compiler's high warning levels when building so you can find those bugs.
That's C, you cannot do much about it. The basic purpose of C is to be fast - a default initialization of the variable takes a few more CPU cycles and therefore you have to explicitly specify that you want to spend them. Because of this (and many other pitfalls) C is not considered good for those who don't know what they are doing :)
The C standard says the behavior of uninitialized auto variables is undefined. A particular C compiler may initialize all variables to zero (or pointers to null), but since this is undefined behavior you can't rely on it being the case for a compiler, or even any version of a particular compiler. In other words, always be explicit, and undefined means just that: The behavior is not defined and may vary from implementation to implementation.
-- Edit --
As pointed out, the particular question was about static variables, which have defined initialization behavior according to the standard. Although it's still good practice to always explicitly initialize variables, this answer is only relevant to auto variables which do not have defined behavior.