Why does std:endl assign zero to an unitialized variable? [duplicate] - c++

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)

Related

c++ : When is a declared variable is initialized without assigning it to any value?

if I compile the code bellow as commenting out the line 13, I'm having a warning message that it says warning: 'test.Test::x' is used uninitialized in this function but if i compile it with the line 13, the compiler isn't warn that Test::x is uninitialized.
And my question is:
when I call line 7 in line 13 why the compiler didn't warn me about uninitialized variable x, if the x is initialized already when is that?
#include <iostream>
class Test
{
public:
int x;
void printX(){ std::cout << x << std::endl; } // ----------------line 7
};
int main()
{
Test test;
// test.printX(); // --------------------------------------------line 13
std::cout << test.x << std::endl;
return 0;
}
If you don't initialize, it is uninitialized. Compilers make their best effort to help you to point out your bugs but not always possible and you cannot rely on those. If you use a latest version of the compiler, you get better warnings.
if the x is initialized already when is that?
No, x is not initialized.
Your question is really confusing. Not exactly sure what you're asking.
At any rate, raw data types are not initialized unless you do so explicitly. Those and PODs. Just initialize all of your data members.

c++ understanding accessing global variables after cleanup does not give some sort of error

I have a question about how global variables work in c++.
I know global variables are evil so that is not the point of this question. I just want a deeper understanding of what is happening in the following example.
#include <cstdint>
#include <iostream>
#include <vector>
class B
{
public:
B();
~B();
private:
static std::vector<int32_t> v_;
};
B::B()
{
std::cout << "v_.size() = " << v_.size() << std::endl;
for (auto i : v_)
std::cout << i << std::endl;
}
B::~B()
{
std::cout << "v_.size() = " << v_.size() << std::endl;
std::cout << "v_[0] = " << v_[0] << std::endl;
std::cout << "v_.at(0) = " << v_.at(0) << std::endl;
for (auto i : v_)
std::cout << i << std::endl;
}
B b;
std::vector<int32_t> B::v_ { 5, -7 };
int main()
{
return 0;
}
Gives this output:
$ ./test
v_.size() = 0
v_.size() = 2
v_[0] = 0
v_.at(0) = 0
0
0
Why is the size of the vector in the destructor of B still 2?
When I access the elements of the vector I get random memory, which I sort of understand because the vector gets cleaned up before B. But to me the size of the vector should be 0 or even way better throw some sort of error when asking for the size. Even when using at() function It doesn't throw an error because the size is still 2.
I also know I can fix this by switching the initialization of b and the vector. My question is more why this specific example doesn't throw some sort of error, cause in my opinion it should.
Note: like my comment: why does this behavior fall under undefined behavior instead of reading or writing an illegal memory location since the vector doesn't exist at that point? I was kinda thinking this would/should generate a seg fault and I don't understand why it doesn't
Undefined behavior means that the behavior of your program is not defined by the C++ standard. A conforming C++ compiler can do anything with a program that has, or will, exhibit undefined behavior (yes, UB can time travel).
Your program exhibits undefined behavior by accessing v_ as an object prior to it being constructed in B::B. Given that it does this, nothing about your programs execution is specified or constrained by the C++ standard.
In this case, the compiler treats the UB access as if it was accessing an empty std::vector. This is valid, because anything is valid. The program then proceeds as-if you hadn't done the UB (other than the above symptom), which is also a valid option.
If we imagine removing the UB in the ctor, during destruction your program again exhibits UB. This time by accessing v_ as a vector object after it was destroyed. Again, by doing this the behavior of your program is not defined or constrained by the C++ standard, before, at, and after the UB.
In this case, it behaves as if you have a vector of 2 values whose values are 0. That is conforming, because anything is conforming.
One of many possibilities is that the data was recycled on the heap, but the pointers where left dangling. Treating the vector's "rotted" data as pointers they still point 2 sizeof(int) apart, and .size() reads that as 2. The data pointed to, however, has been recycled on the heap, and there is different data there.

How does C++ proceed for += with a variable without value? [duplicate]

This question already has answers here:
What happens when I print an uninitialized variable in C++? [duplicate]
(4 answers)
Closed 6 years ago.
i am currently learning C++ and i had a question about some "weird" things i noticed while testing what i have learnt.
So i use this :
int marc[9];
int sum = 0;
for (int x =0; x < 9; x++) {
marc[x] = x*4;
sum += marc[x];
}
cout << sum << endl;
And i get a normal result which is 144
However, if i changed
int sum = 0;
to
int sum;
I got a crazy result like 19557555002
So i was wondering what is happening in the second case?
Thanks for your answer :)
You are operating on uninitialized memory in the second case. Non-static local variables are not initialized to zero by the runtime like in other languages, if you need sum to have a defined value, you must initialize it yourself. The 19557555002 will be the integer interpretation of any bytes that were present at the memory address allocated for sum.
Further reading: What happens to a declared, uninitialized variable in C? Does it have a value?
Its called an undefined behavior and it happens when you don't initialize your variables.
int sum;
above code can only declare a variable but it doesn't initialize it by default so the variable contains a garbage value.
this creates an uninitialized int int sum;
it can have "garbage" values, and this is exactly what happened to you
how this happens: let's say you use an int x in address y, and sets it to 19557555002. now, lets say you "leave" that address (go out of scope, program terminates, OS takes that memory...) and someone else takes it because he wants to put there a new int. if he just declares his int, without initializing it, his int can be stationed (if the OS so desires...) in address y, that previously used to hold your int, which means in address y, he will find 19557555002. That is what could happen to you if you don't initialize variables.
Memory for local variables is typically allocated on the stack. This means that without some initialization, they will hold some data that was residing there previously.
As others said it is undefined behavior, but practically, on most implementations, it results in effects like this:
void foo()
{
int a = 5;
}
void bar()
{
int b;
std::cout << b;
}
void someCaller()
{
foo();
bar();
}
On most implementations, this will usually result in the printing of 5 on the stdout.
Note that some compilers like MSVC initialize all variables in Debug configuration, but usually any kind of optimization flags will avoid initializing memory, if not explicitly requested.

Two different double values after adding a string variable

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.

Why the var and * to var gives diff values in this example of const_cast

Check this example for const_cast of int.
I am using VC++ 2008 to compile this.
#include <iostream>
using namespace std;
void main() {
const int x=0;
int y=90;
int *p = const_cast<int *> (&x);
*p=y;
cout<<" value of x: "<<x<<" addr of x "<<&x<<endl
<<" and *p : "<<*p<<" and addr p "<<p<<endl;
}
================
The output is
value of x: 0 addr of x 0012FF60
and *p : 90 and addr p 0012FF60
You should not const_cast a variable defined as const. I don't have the standard at hand but I'm fairly certain it defines such an operation as resulting in undefined behaviour.
For an example of why this results in undefined behaviour consider an MCU where things defined as const are stored in non-volatile memory (flash, EEPROM or something even less volatile).
There's more to read in the C++ FAQ Lite.
For the following program
#include <iostream>
int main() {
const int x=0;
int y=90;
int *p = const_cast<int *> (&x);
*p=y;
std::cout << " value of x: " << x << " addr of x " << &x << '\n'
<< " and *p : " << *p << " and addr p " << p << '\n';
return 0;
}
VC9 prints the same address for me. However:
You are invoking undefined behavior, because you are not allowed to cast away const from an object if that object was a real const value. (OTOH, you are, for example, allowed to cast away const from a const reference if that reference refers to a non-const value.)
In theory, when you invoke undefined behavior, according to the C++ standard your program might work as you expect, or it might not, or it might do so only on Sundays, or unless it's a holiday and full moon. But it might just as well format your HD, blow up your monitor, and make your girlfriend pregnant. According to the C++ standard, all this (and an infinite amount of other possibilities), are Ok.
In practice, such a program might print out funny addresses.
The compiler might completely optimize away all your code and just put in dummy values for printing. It shouldn't, however, do so for Debug builds. (Although that's a QoI issue, not a requirement.)
The compiler is optimizing away the aliasing. Try it in debug mode, with optimizations disabled.
edit
The compiler is optimizing away the aliasing, yes, but it's not an error in the optimization. Rather, the code is doing something undefined, which is leading to an unwanted but legal behavior. Staffan's answer clarifies this.
As the FAQ said, in almost all cases where you're tempted to use const_cast, you should be using mutable instead. If, as in the sample code here, you can't use mutable, this is an indication that something might be wrong.
maybe it was optimized by the compiler. he have all rights to do this.
it is drawback of misusing const_cast.
never use const_cast in such way.