I compiled the following code using g++
#include <iostream>
int main()
{
double res;
std::cout << res << std::endl;
return 0;
}
That gave the following result
g++ foo.c
./a.out
0
But after a small change
#include <iostream>
int main()
{
std::string input;
double res;
std::cout << res << std::endl;
return 0;
}
It became
g++ foo.c
./a.out
2.0734e-317
Why are the results different and why the number 2.0734e-317?
Your code invokes undefined behaviour. Since automatic variables of built-in types are not deafult-initialized unless specifically aksed, value for variable res is undefined in your code. It can be anything.
Why you have different value their based on different code structure is understandable - since no one is setting the value for the variable, you are left with whatever is left in the stack memory after previous calls. Pure random.
In particular, in the former example, the stack memory is not used at all before you declare your res variable. As a result, you use untouched stack memory, which is 0 initialize. In the latter case, you have already defined string variable, and called it's constructor. Constructor used stack memory for it's own purpose, and left those values there. Now the res variable is constructed in used stack memory, and you see some random values there.
It's arbitrary.
You did not initialise your variable. It has an unspecified value.
Therefore, reading its "value" has undefined behaviour. Anything can happen.
Not only can you get any value (due to internal assumptions that you cannot rationalise about from outside of the black box of the compiler implementation), but you could also/instead open a black hole or kill my cat, and I would not be terribly happy about either of those outcomes.
You are outputting an uninitialized variable. So it's value can be anything.
Related
This question already has answers here:
Uninitialized variable behaviour in C++
(4 answers)
Closed 3 years ago.
Please, consider the following C++ snippet:
#include <iostream>
int main() {
int x;
std::cout << x << '\n';
return 0;
}
as expected the result printed will be unpredictable since the variable x has not been initialized. If you run it may get 458785234 and 348934610 the second time. However, if you change the code the following way:
#include <iostream>
int main() {
int x;
std::cout << x << std::endl;
return 0;
}
Now, the x printed is always equal to zero. Why is that? Note the only change introduced is the std::endl. Can anybody explain why this assigns 0 to x variable?
as expected the result printed will be unpredictable ...
Now, the x printed is always equal to zero. Why is that?
It is so because the behaviour is undefined.
You expected the number to be "unpredictable". It seems that you didn't predict the number to be zero. This should be according to your expectations.
You did nothing to make the number non-zero, so why would you expect the number to be non-zero?
On the other hand, you may have been expecting that the behaviour doesn't change because the change to the program seems to be unrelated. That expectation is ill-advised. Undefined behaviour is not guaranteed to be the same undefined behaviour if you change any part of the program. In fact, the behaviour is not guaranteed to be the same even if you don't change anything. On the other hand, the behaviour is also not guaranteed to be different. Nothing about the behaviour of the program is guaranteed. That is what undefined behaviour means.
With gcc 5.4.0 on Ubuntu 16.04 I'm getting 0 in both versions of your code. But that doesn't matter since x is uninitialized and trying to read it is undefined behavior. Anything may happen depending on the particular compiler and system being used with no guarantee for any particular behavior.
Now consider the following:
#include <iostream>
void foo() {
int x;
std::cout << x << std::endl;
}
void bar() {
int y = 123;
std::cout << y << std::endl;
}
int main() {
foo();
bar();
foo();
return 0;
}
On my machine it prints:
0
123
123
So my guess is that my compiler does zero initialization of stack area before program starts but doesn't bother to do so later to avoid unnecessary works.
But as I pointed out before, these behaviors are undefined. There is no requirement from standard regarding this and as a result we must not assume anything specific to happen always.
It's undefined behavior what you get is compiler call
With Microsfot Visual C++ it doesn't even compile (error C4700: uninitialized local variable 'x' used)
How variable int a is in existence without object creation? It is not of static type also.
#include <iostream>
using namespace std;
class Data
{
public:
int a;
void print() { cout << "a is " << a << endl; }
};
int main()
{
Data *cp;
int Data::*ptr = &Data::a;
cp->*ptr = 5;
cp->print();
}
Your code shows some undefined behavior, let's go through it:
Data *cp;
Creates a pointer on the stack, though, does not initialize it. On it's own not a problem, though, it should be initialized at some point. Right now, it can contain 0x0badc0de for all we know.
int Data::*ptr=&Data::a;
Nothing wrong with this, it simply creates a pointer to a member.
cp->*ptr=5;
Very dangerous code, you are now using cp without it being initialized. In the best case, this crashes your program. You are now assigning 5 to the memory pointed to by cp. As this was not initialized, you are writing somewhere in the memory space. This can include in the best case: memory you don't own, memory without write access. In both cases, your program can crash. In the worst case, this actually writes to memory that you do own, resulting in corruption of data.
cp->print();
Less dangerous, still undefined, so will read the memory. If you reach this statement, the memory is most likely allocated to your program and this will print 5.
It becomes worse
This program might actually just work, you might be able to execute it because your compiler has optimized it. It noticed you did a write, followed by a read, after which the memory is ignored. So, it could actually optimize your program to: cout << "a is "<< 5 <<endl;, which is totally defined.
So if this actually, for some unknown reason, would work, you have a bug in your program which in time will corrupt or crash your program.
Please write the following instead:
int main()
{
int stackStorage = 0;
Data *cp = &stackStorage;
int Data::*ptr=&Data::a;
cp->*ptr=5;
cp->print();
}
I'd like to add a bit more on the types used in this example.
int Data::*ptr=&Data::a;
For me, ptr is a pointer to int member of Data. Data::a is not an instance, so the address operator returns the offset of a in Data, typically 0.
cp->*ptr=5;
This dereferences cp, a pointer to Data, and applies the offset stored in ptr, namely 0, i.e., a;
So the two lines
int Data::*ptr=&Data::a;
cp->*ptr=5;
are just an obfuscated way of writing
cp->a = 5;
I am a c++ learner. Others told me "uninitiatied pointer may point to anywhere". How to prove that by code.?I made a little test code but my uninitiatied pointer always point to 0. In which case it does not point to 0? Thanks
#include <iostream>
using namespace std;
int main() {
int* p;
printf("%d\n", p);
char* p1;
printf("%d\n", p1);
return 0;
}
Any uninitialized variable by definition has an indeterminate value until a value is supplied, and even accessing it is undefined. Because this is the grey-area of undefined behaviour, there's no way you can guarantee that an uninitialized pointer will be anything other than 0.
Anything you write to demonstrate this would be dictated by the compiler and system you are running on.
If you really want to, you can try writing a function that fills up a local array with garbage values, and create another function that defines an uninitialized pointer and prints it. Run the second function after the first in your main() and you might see it.
Edit: For you curiosity, I exhibited the behavior with VS2015 on my system with this code:
void f1()
{
// junk
char arr[24];
for (char& c : arr) c = 1;
}
void f2()
{
// uninitialized
int* ptr[4];
std::cout << (std::uintptr_t)ptr[1] << std::endl;
}
int main()
{
f1();
f2();
return 0;
}
Which prints 16843009 (0x01010101). But again, this is all undefined behaviour.
Well, I think it is not worth to prove this question, because a good coding style should be used and this say's: Initialise all variables! One example: If you "free" a pointer, just give them a value like in this example:
char *p=NULL; // yes, this is not needed but do it! later you may change your program an add code beneath this line...
p=(char *)malloc(512);
...
free(p);
p=NULL;
That is a safe and good style. Also if you use free(p) again by accident, it will not crash your program ! In this example - if you don't set NULL to p after doing a free(), your can use the pointer by mistake again and your program would try to address already freed memory - this will crash your program or (more bad) may end in strange results.
So don't waste time on you question about a case where pointers do not point to NULL. Just set values to your variables (pointers) ! :-)
It depends on the compiler. Your code executed on an old MSVC2008 displays in release mode (plain random):
1955116784
1955116784
and in debug mode (after croaking for using unitialized pointer usage):
-858993460
-858993460
because that implementation sets uninitialized pointers to 0xcccccccc in debug mode to detect their usage.
The standard says that using an uninitialized pointer leads to undefined behaviour. That means that from the standard anything can happen. But a particular implementation is free to do whatever it wants:
yours happen to set the pointers to 0 (but you should not rely on it unless it is documented in the implementation documentation)
MSVC in debug mode sets the pointer to 0xcccccccc in debug mode but AFAIK does not document it (*), so we still cannot rely on it
(*) at least I could not find any reference...
I'm using CodeBlocks 13.12, g++ compiler and my local variables are all being initializated to 0.
I would to know if there's a way to avoid the compiler to set 0 to all my variables. I would like to have garbage value in them.
For example:
#include <iostream>
using namespace std;
int main(){
int a, b;
cout << a << " " << b;
return 0;
}
The output is:
0 0
I don't want a and b to be zero. They should contain junk values.
Thanks in advance
The compiler behaves differently in this regard when building with/without optimization. I'm guessing you are building without optimization and that's why the compiler zero initializes variables.
But, when that is said; don't go around reading uninitialized variables. That is undefined behaviour. While you may often just get a 'garbage' value, the compiler is actually free to generate whatever code it wants when it sees that your program is undefined. This includes not emitting any code at all, emitting the code you expect as well as rewriting other parts of your program. Don't invoke undefined behaviour.
If you want a random value, use the <random> facilities - http://en.cppreference.com/w/cpp/numeric/random
Look at this program:
#include <iostream>
using namespace std;
int main()
{
const int x = 0;
int *p;
p=(int*)&x;
(*p)++;
cout<<x<<endl;
cout<<*p;
}
As you see above, I declared x as a const int, and using casting, a non const pointer named p is points to it. In the middle of the body of my program, I increased the value of x by one using (*p)++ (How is it possible, while x is defined as const?)
Now,when I print *p and x, they returns different values, while *p is supposed to point to address of x :
ap1019#sharifvm:~$ ./a.out
0
1
Why?
The change of variable after constant removal causes the undefined behaviour, in some cases it will just work as if it wouldn't be const, in some it will cause the memory violation error, in some, it will turn your computer into the rabbit which will try to kill you...
A bit of background on the behaviour. Imagine you are a compiler. You encounter the variable:
const int blah = 3;
And then you encounter the following operation:
int foo = 4 + blah;
As you are smart compiler and you know that blah is constant - therefore it will not change, instead of reading the value from the blah, you can exchange the value from get the blah storage place in memory read it to simply add the 3 to 4 and assign it to foo.
Infant you will probably assign 7 straight away because doing the addition is pointless each time you run the program.
Lets now get into the casting away the const part.
Some really sneaky programmer is doing the following:
int * blah_pointer = (int *) & blah;
Then he is increasing the blah value by doing this operation:
(*blah_pointer)++;
What will happen - if the variable is not in the protected memory (not read only) the program will just increase the value of variable stored in memory.
Now when you will read the value which is stored in the pointer you will get the increased value!
Ok but why is there an old, unchanged value if you are reading just the blah I hear you ask:
std::cout << blah;
It is there, because the compiler try to be smart and instead of actually reading the value from blah it will just exchange it to a constant value to blah, so instead of reading it it will actually exchange it to std::cout << 3.
The undefined part is changing the constant value - you can't ever know whether the value will be stored in protected or unprotected region therefore you can't tell what will happen.
If you want the compiler to actually check the value each time it encounters it just change the definition from:
const int blah = 3;
to
const volatile int blah = 3;
It will tell the compiler the following, even though the program I am writing is not allowed to change the blah value, it may be changed during the execution of the program, therefore do not try to optimise the access to the memory and read it every time the value is used.
I hope this makes it clearer.
I think, in compilation step, your compiler will replace all your constant variables with its values (it's like #define), it's the way GNU GCC compiler optimize the code.
I'm not 100% sure about it, but i've got the same issue while learning C/C++ syntax, and it's the conclusion that i've made after disassebling (converting the binary executable to assembler code) my program.
Anyways, just try to disassemble your output and see what is really happening.