C++ functions and scope of variables - c++

#include<iostream>
using namespace std;
void fun(int a) {
int x;
cout << x << endl;
x = a;
}
int main() {
fun(12);
fun(1);
return 0;
}
The output of this code is as follows:
178293 //garbage value
12
why are we getting 12 and not garbage value instead??

why are we getting 12 and not garbage value instead??
In theory, the value of x could be anything. However, what's happening in practice is that two calls to fun one after the other is responsible for the previous value of x to be still on the stack frame.
Let's say the stack frame is structured as below:
arguments
return value
local variables
In your case,
Memory used for arguments is equal to sizeof(int).
The compiler may omit using any memory for the return value since the return type is void.
Memory used for local variables is equal to sizeof(int).
When the function call is made the first time, the value in the arguments part is set to 12. The value in the local variables is garbage, as you noticed. However, before you return from the function, you set the value of the local variable to 12.
The second time the function is made, the the value of the argument is set to 1. The value in the local variable is still left over from the previous call. Hence, it is still 12. If you call the function a third time, you are likely to see the value 1 in the local variable.
Anyway, that's one plausible explanation. Once again, remember that this is undefined behavior. Don't count on any specific behavior. The compiler could decide to scrub the stack frame before using it. The compiler could decide to scrub the stack frame immediately after it is used. The compiler could do whatever it wants to do with the stack frame after it is used. If there is another call between the calls to fun, you will most likely get completely different values.

You have not initialized the value x when printing it. Reading from uninitialized memory is UB, i.e., there are no guarantees as to what will happen. It could output a random number, or invoke an unlikely combination of bits that will do something unexpected.

Reading an uninitialized integer is UNDEFINED BEHAVIOR, that means that it can do literally anything, can print anything. It can format your hard drive or collapse the observable universe! Basically I dont know compiler implementations that do so but theoretically they can!

Related

Is the value of a variable always guaranteed to be 1 word away from the variable created outside of scope if it comes immediately after?

int main()
{
{int x = 532;}
int xc;
int x = *(&xc+1);
cout << x << endl; // prints 532
}
I create an int variable with a value of 532 and then it immediately goes out of scope.
I then create another int variable right after so that it has an address of 1 word before x.
I then assign that value of whatever was one word past xc to x and print it, and it has the value of 532.
Is this guaranteed to happen? Why/why not?
No, the arrangement and padding (and even the existence) of variables on the stack is implementation-dependent, and what you have here is Undefined Behavior. The language specifies that you must not use a pointer to access the memory of any object other than the one it points to.
In this case, &xc + 1 points to memory that lies outside the allocation of xc. You cannot read or write to this location and expect any kind of predictable result. Note that it is actually a valid pointer -- you are allowed to point "one-past-the-end" of an allocation, provided you never dereference that address.
To explain what's actually happening in your case: your variables are being pushed onto the stack, and the stack memory extends in the direction of lower addresses. It appears your compiler didn't bother to unwind the stack after the original x went out of scope. Alternatively, multiple values of 532 might have been initialized in memory, or in a register, and the value you're reading might not be the one that was stored at x. All this said, even this program on your computer with your compiler does not guarantee this behavior.
The original variable x could be optimized away by the compiler completely because it is not used.
The value of xc is uninitialized. Its location (if any) on the stack is not guaranteed. Even though x had additional scope, the compiler is not required to push and pop stack locations if it doesn't want to.
The compiler is not required to understand that you're aliasing x via xc because, as already mentioned such behavior is not defined.

Implications of not assigning the return value of a function to a variable

I'm going through some introductory C++ exercises, one of which is: What's going to be on the screen after running this code:
int& testMethod (int& a){
int c = a+a;
return c;
};
int main() {
int z = 5;
int* y = new int (testMethod(z));
int r = 25;
testMethod(r);
std::cout<<*y;
return 0;
}
My questions are:
Am I right that this is an example of UB as the value returned by testMethod on the second call is not getting assigned to a variable?
Is it true that the return value, although not assigned to a variable, might still be recovered but it depends?
For No 2, I'm just trying to confirm my understanding of how the stack works, which is as follows. When a function returns a value and the value gets assigned to a variable, the result of the calculations is firstly stored on the stack as retval at some memory location and then gets assigned to the variable, i.e. written to another memory location. The stack pointer then moves up (again, from what I understand, the 'top' of the stack is actually its 'bottom' as the pointer moves from the largest address to the smallest). But retval is still there for some time until it gets overwritten by another piece of data (which might happen almost instantly).
This second question arose when I was looking for an answer to the first question on SO and found this thread, as the two top (by votes) posts answer differently.
How automatic allocation is implemented on your particular platform is irrelevant. Your codes does trigger UB, not because you ignore the return value of testMethod (which, by the way, is not a method) but on the contrary because the following line uses it:
int* y = new int (testMethod(z));
The issue is that testMethod always returns a dangling reference to what was its local variable c. Using this reference to initialize the dynamically-allocated int triggers UB.
Predictably, enabling warnings (which you should always do) produces the following:
warning: reference to stack memory associated with local variable 'c' returned [-Wreturn-stack-address]
Am I right that this is an example of UB as the value returned by
testMethod on the second call is not getting assigned to a variable?
Maybe you didnt notice yet, but you are ignoring the returned value all the time (sloppy speaking). For example std::cout << *y; returns a reference to std::cout, otherwise you could not chain it as in
std::cout << "hello" << "world";
No. Ignoring the returned value is not undefined. Sometimes you cannot avoid to ignore the returned value (just another example: assignment usually returns a reference, ie you can write a = b = c; but usually you just write b = c; a = b;).
For 2) you are too much considering implementation details. Dont overcomplicate it. You ignore the value, thats all.
PS: your code has UB, but for completely different reason (see other answer).

Local Variables Being Passed ( C++)

I have encountered a problem in my learning of C++, where a local variable in a function is being passed to the local variable with the same name in another function, both of these functions run in main().
When this is run,
#include <iostream>
using namespace std;
void next();
void again();
int main()
{
int a = 2;
cout << a << endl;
next();
again();
return 0;
}
void next()
{
int a = 5;
cout << a << endl;
}
void again()
{
int a;
cout << a << endl;
}
it outputs:
2
5
5
I expected that again() would say null or 0 since 'a' is declared again there, and yet it seems to use the value that 'a' was assigned in next().
Why does next() pass the value of local variable 'a' to again() if 'a' is declared another time in again()?
http://en.cppreference.com/w/cpp/language/ub
You're correct, an uninitialized variable is a no-no. However, you are allowed to declare a variable and not initialize it until later. Memory is set aside to hold the integer, but what value happens to be in that memory until you do so can be anything at all. Some compilers will auto-initialize variables to junk values (to help you catch bugs), some will auto-initialize to default values, and some do nothing at all. C++ itself promises nothing, hence it's undefined behavior. In your case, with your simple program, it's easy enough to imagine how the compiler created assembly code that reused that exact same piece of memory without altering it. However, that's blind luck, and even in your simple program isn't guaranteed to happen. These types of bugs can actually be fairly insidious, so make it a rule: Be vigilant about uninitialized variables.
An uninitialized non-static local variable of *built-in type (phew! that was a mouthful) has an indeterminate value. Except for the char types, using that value yields formally Undefined Behavior, a.k.a. UB. Anything can happen, including the behavior that you see.
Apparently with your compiler and options, the stack area that was used for a in the call of next, was not used for something else until the call of again, where it was reused for the a in again, now with the same value as before.
But you cannot rely on that. With UB anything, or nothing, can happen.
* Or more generally of POD type, Plain Old Data. The standard's specification of this is somewhat complicated. In C++11 it starts with §8.5/11, “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.”. Where “automatic … storage duration” includes the case of local non-static variable. And where the “no initialization” can occur in two ways via §8.5/6 that defines default initialization, namely either via a do-nothing default constructor, or via the object not being of class or array type.
This is completely coincidental and undefined behavior.
What's happened is that you have two functions called immediately after one another. Both will have more or less identical function prologs and both reserve a variable of exactly the same size on the stack.
Since there are no other variables in play and the stack is not modified between the calls, you just happen to end up with the local variable in the second function "landing" in the same place as the previous function's local variable.
Clearly, this is not good to rely upon. In fact, it's a perfect example of why you should always initialize variables!

Uninitialized variable behaviour in C++

I've checked myself, I wrote a program like this
int main() {
int i;
cout << i;
return 0;
}
I ran the program a few times and the result was same all the time, zero.
I've tried it in C and the result was the same.
But my textbook says
If you don’t initialize an variable that’s defined
inside a function, the variable value remain undefined.That means the element takes on
whatever value previously resided at that location in memory.
How's this possible when the program always assign a free memory location to a variable? How could it be something other than zero(I assume that default free memory value is zero)?
How's this possible when the program always assign a free memory
location to a variable? How could it be something rather than zero?
Let's take a look at an example practical implementation.
Let's say it utilizes stack to keep local variables.
void
foo(void)
{
int foo_var = 42;
}
void
bar(void)
{
int bar_var;
printf("%d\n", bar_var);
}
int
main(void)
{
bar();
foo();
bar();
}
Totally broken code above illustrates the point. After we call foo, certain location on the stack where foo_var was placed is set to 42. When we call bar, bar_var occupies that exact location. And indeed, executing the code results in printing 0 and 42, showing that bar_var value cannot be relied upon unless initialized.
Now it should be clear that local variable initialisation is required. But could main be an exception? Is there anything which could play with the stack and in result give us a non-zero value?
Yes. main is not the first function executed in your program. In fact there is tons of work required to set everything up. Any of this work could have used the stack and leave some non-zeros on it. Not only you can't expect the same value on different operating systems, it may very well suddenly change on the very system you are using right now. Interested parties can google for "dynamic linker".
Finally, the C language standard does not even have the term stack. Having a "place" for local variables is left to the compiler. It could even get random crap from whatever happened to be in a given register. It really can be totally anything. In fact, if an undefined behaviour is triggered, the compiler has the freedom to do whatever it feels like.
If you don’t initialize an variable that’s defined inside a function, the variable value remain undefined.
This bit is true.
That means the element takes on whatever value previously resided at that location in memory.
This bit is not.
Sometimes in practice this will occur, and you should realise that getting zero or not getting zero perfectly fits this theory, for any given run of your program.
In theory your compiler could actually assign a random initial value to that integer if it wanted, so trying to rationalise about this is entirely pointless. But let's continue as if we assumed that "the element takes on whatever value previously resided at that location in memory"…
How could it be something rather than zero(I assume that default free memory value is zero)?
Well, this is what happens when you assume. :)
This code invokes Undefined Behavior (UB), since the variable is used uninitialized.
The compiler should emit a warning, when a warning flag is used, like -Wall for example:
warning: 'i' is used uninitialized in this function [-Wuninitialized]
cout << i;
^
It just happens, that at this run, on your system, it had the value of 0. That means that the garbage value the variable was assigned to, happened to be 0, because the memory leftovers there suggested so.
However, notice that, kernel zeroes appear relatively often. That means that it is quite common that I can get zero as an output of my system, but it is not guaranteed and should not be taken into a promise.
Static variables and global variables are initialized to zero:
Global:
int a; //a is initialized as 0
void myfunc(){
static int x; // x is also initialized as 0
printf("%d", x);}
Where as non-static variables or auto variables i.e. the local variables are indeterminate (indeterminate usually means it can do anything. It can be zero, it can be the value that was in there, it can crash the program). Reading them prior to assigning a value results in undefined behavior.
void myfunc2(){
int x; // value of x is assigned by compiler it can even be 0
printf("%d", x);}
It mostly depends on compiler but in general most cases the value is pre assumed as 0 by the compliers

What happens to unused function return values?

If I have a program:
#include <iostream>
using namespace std;
int TestIntReturn(int &x, int &y)
{
x = 1000;
y = 1000;
return x+y;
}
int main()
{
int a = 1;
int b = 2;
cout << a << " " << b << endl;
TestIntReturn(a,b);
cout << a << " " << b << endl;
}
what happens to the return value of TestInReturn(a,b) since it is unused?
Since you're talking about Windows, we'll assume an x86 processor.
In this case, the return value will typically be in register EAX. Since you're not using it, that value will simply be ignored, and overwritten the next time some code that happens to write something into EAX executes.
In a fair number of cases, if a function has no other side effects (just takes inputs and returns some result) the compiler will be able to figure out when you're not using the result, and simply not call the function.
In your case, the function has some side effects, so it has to carry out those side effects, but may well elide code to compute the sum. Even if it wasn't elided, it can probably figure out that what's being added are really two constants, so it won't do an actual computation of the result at run-time in any case, just do something like mov EAX, 2000 to produce the return value.
It is discarded; the expression TestInReturn(a,b) is a discarded-value expression. Discarding an int has no effect, but discarding a volatile int (or any other volatile-qualified type) can have the effect of reading from memory.
The return value simply gets discarded. Depending on the exact scenario the optimizer might decide to optimize away the whole function call if there are no observable side effects (which is not the case in your example).
So, upon return from TestIntReturn, the function will push the return value on the stack, the caller will then adjust the stack frame accordingly, but won't copy the returned value from the stack into any variable.
Nothing - it goes into the ether, and is not stored/used. The return value itself is an rvalue or temporary; I believe the compiler will optimize even the temporary creation out due to it not actually being used.
The return value is stored on the stack and popped off when the function returns. Since it is not being assigned to a variable by the caller, it is just discarded when the stack is popped.
Everybody answered correctly - the return value in this case is simply discarded, and in this specific example, you can ignore it.
However, if the return value is a pointer to memory allocated inside the function, and you ignore it, you'll have a memory leak.
So some function values you can't just ignore, but in this case - you can.
In the case of primitive types, nothing happens to it. It is
just ignored. In the case of class types, the returned object
will be destructed, without anything else happening to it.