Why does gcc give me this result? - c

When I run this code gcc gives me the output 10.
Can someone explain to me why it gives me 10? :)
#include <stdio.h>
int f(int x) {
int y;
y = 2*x;
}
int g() {
int z;
return z;
}
int main() {
int x=5;
f(x);
printf("%d\n",g());
}

this is undefined behavior - you are referencing a variable which has no value set to it. likely, it gives 10 because the compiler has used the same memory location for the variable in f(), but there is no guarantee of that, it should not be depended on, and is nothing more than a curiosity.

There's nothing to explain. Your code exhibits undefined behaviour on two separate, unrelated occasions: First f isn't returning anything despite being declared as returning int, and second because g returns an uninitialized value.
Practically, the way the functions will be put on the call stack will have caused the local y (which eventually has the value 10) to be in the same place as the return value of g() in the printf call, so you happen to see the value 10. But that's more or less a matter of luck.

Here:
int g() {
int z;
return z;
}
This reads:
int g():
reserve memory for an integer, call it z.
return whatever is in that reserved memory.
You never used that reserved memory for your integer. Its value is whatever was at that address before you chose to use it (or not use it, rather). That value could be anything.
You do the same in your other function. What you are doing is reading uninitialized memory. You can google that up for further information. See also the "stack" and the "heap", dynamic memory, and other related topics.

g returns an unitialized varable from the stack, in your example that location was last set by the F function giving you your answer of x*2 = 10

Because you're not initializing z, and it's using the same location on the stack as y. Since you're not initializing it the old value is still there.

This is a perfect example of why people fear optimizations and when they brag about finding compiler bugs to their bosses. This code as others have alluded to will throw warnings about using uninitialized variables in g(). With your compiler settings, it is using the old value on the stack from the call to f(5). With different compiler optimization settings, it will likely have effects on how variables end up on the stack and you'll end up getting a different results when you make changes which appear unrelated. This is undefined behavior and there is no guarantees on what value will result however it is usually easy to explain by understanding the call order and how the compiler sets up the stack. If there are warnings when you're troubleshooting weird behavior like this, fix the warnings first then start asking questions about why.

Related

C variable initialization and execution [duplicate]

This question already has answers here:
Is un-initialized integer always default to 0 in c?
(4 answers)
Closed 1 year ago.
In C, we know that without initializing a variable, it holds a garbage value. Yet in online compilers and also, in an IDE, when I tried this program it got compiled and there was a perfect output. When I tried to print the same without the while loop, it returned a garbage value. So, is not initializing fine?
#include <stdio.h>
int main() {
int j;
while(j<=10){
printf("\n %d",j);
j=j+1;
}
}
Try disassembling your code, for example "gcc -S test.c", so you can see that there is no instruction dedicated to initializing the integer "j" with or without loop. Greetings.
… it holds a garbage value.
When anybody says an object has a garbage value, they are being imprecise with language.
There is no value that is a garbage value. For 32-bit two’s complement integers, there are the values −2,147,483,648 to +2,147,483,647. Each of them is a valid value. None of them is a garbage value.
What it actually means to say something has a garbage value, if the speaker understands C semantics, is that the value of the object is uncontrolled. It has not been set to any specific value, and therefore whatever value you get from using it is a happenstance of circumstances. It may be some value that was in the memory of the object before it was reserved to be the memory for that object.
However, it might be other things. When an object is uninitialized, the C standard not only has no requirement that the memory of the object have any particular value, it has no requirement that the object behave as if it had any fixed value at all. This frees the compiler for purposes that are useful for optimization in other situations. But it means that, if you have int x; printf("%d\n", x); int y = x+3; printf("%d\n", y);, the compiler does not have to load x from memory each time it is used. Because x is uninitialized, the compiler is not required to do any work to load it from memory. For the printf("%d\n", x);, the compiler might let x be whatever value is in the register that would be used to pass the second argument to printf. For the int y = x+3;, the compiler might let x be whatever is in some other register that it would use to hold the value of x if x were defined. This could be a different register. So printf("%d\n", x); might print “47” while int y = x+3; printf("%d\n", y); prints “−372”, not “50”.
Sometimes an uninitialized object might behave as if it started with the value zero. This is not uncommon in short programs such as the one in the question, where nothing has used the stack much yet, so the part of it reserved for j is still in the initial state the program loader put it in, filled with zeros. But that is happenstance. When you change the program, the compiler might use a different part of the stack for j, and that part might not have zeros in it, because it was used by some of the initial program start-up code that runs before main starts.
Always avoid use a uninitialized variables, because it cause undefined behavior.
Uninitialized variables
Unlike some programming languages, C/C++ does not initialize most variables to a given value (such as zero) automatically. Thus when a variable is assigned a memory location by the compiler, the default value of that variable is whatever (garbage) value happens to already be in that memory location! A variable that has not been given a known value (usually through initialization or assignment) is called an uninitialized variable.
For your reference:
https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+not+read+uninitialized+memory
https://www.learncpp.com/cpp-tutorial/uninitialized-variables-and-undefined-behavior/

Peculiarity in functions of "C" Language [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Undefined, unspecified and implementation-defined behavior
(9 answers)
Closed 2 years ago.
Since i am new to C Language i was learning it from tutorials point when i encountered a peculiarity in functions which got my head banging while understanding it.
I have learnt that if variables are defined inside a function then there scope is local to that function and whenever the control transfers from function the variables are no more available and cleaned.
But its not in the case i have created, the program below is still printing the value of variable p which is defined in the test function so when control from test function is transferred why i am still able to get its value? its still printing the value of variable p that is 80 in screen why?
#include <stdio.h>
int *test();
int main()
{
int *ab
ab = test();
printf("%d\n",*ab);
return 0;
}
int *test()
{
int p = 80;
return (&p);
}
Help me understand this peculiarity Please.
What you are experiencing is a symptom of undefined behavior.
A variable's address is no longer valid after its lifetime ends. When you attempt to dereference that address, you may see the value you had before, or you may see something else.
Try duplicating the printf call in main and you'll likely see a different value.
What is most likely happening is that before the first call to printf the area of memory that contained p hadn't yet been overwritten. Then when printf is actually called, the stack frame for that function is using the same memory that the stack frame for test was using and the memory previously used by p is now overwritten. So when you dereferences ab in main after calling printf you'll see whatever value that function placed there.
Accessing an out-of-scope variable is Undefined Behaviour , and hence, by definition, results can vary infinitely and unpredictably, as variables change (compiler flags, OS, etc.)
Your variable does go out of scope but this only means it is no longer 'reserved'. However, unlike newer languages where this may raise compile-time errors, in C this is merely a warning, which may appear if you specifically ask the compiler to give you extra warnings.
So the code will compile.
Here, the variable goes out of scope, but, assumably, no further usage of memory occurs , and so the value at the address of test stays same . If more variables were declared/initialised/used , then likely that address would have been overwritten with another value, and you would have printed something unexpected - to be real, even this result was unexpected, hence your question !
The thing to remember is - variables in C are like chairs in a hall(which is akin to memory). The chair's position, the number of chairs is all static/fixed. What can be changed is who sits at what chair.
So, if you ask a friend to sit at a convenient chair and 5 minutes later tell him he is no longer required , whether he stays there or gets up and someone takes his place is something you cannot predict without looking and reading at an out-of-scope address is similarly undefined , since it cannot be predicted beforehand !
Other analogies may be parking spaces, ship-containers, etc.
The difference is that the address won't be overwritten / 'deleted' until something else comes up which needs to be stored (this is also how Disks manage 'deletion' which is actually nothing but un-reserving hardware locations) .
And when you think about it, it makes a lot of sense from the efficiency standpoint - you no longer have to waste time doing a useless 'overwrite with 0' or whatever and instead only write when you have a real value to store to memory !
( 1 operation instead of 2, half the work.)
Even though the variable shouldn't be "existing" anymore, the computer is a little bit lazy, and it won't delete the value at an address.
That is how you can manipulate the memory, if you try to see memory that doesn't belong to your program, you'll be able to see some weird values, because they stay in the memory even though they aren't used anymore.
Here is an example that may illustrate the UB you're looking at:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int *test();
void run_random();
int main()
{
srand(time(NULL));
int *ab;
int i=0, N = 5;
for (i=0; i<N; ++i){
ab = test();
run_random();
printf("%d\n",*ab);
}
return 0;
}
int *test()
{
int p = 80;
return (&p);
}
void run_random()
{
int i=0, N=1000;
for (i=0; i<N; ++i){
int rvar = rand();
}
}
In your code, the variable from test() happens to still have the expected value on the stack memory. This is what I see when re-running the function in a loop - *ab is still equal to 80, you can see it too if you comment out the run_random() call.
But when I add the second call, the call to run_random() - I start getting ab equal to N in the run_random() i.e. 1000, as that memory location is now populated with a different variable's value (it was free to use by the OS to begin with, as soon as test() stopped executing).
In your case you may end up seeing something else, of course, perhaps even still the expected value. That is the point of UB, you don't really know what will pop-up.

Can't understand the output of this code stack storage function call c

I had the following code, however I don't understand what and why it outputs what it does.
int main(){
int *i;
int *fun();
i=fun();
printf("%d\n",*i);
printf("%d\n",*i);
}
int *fun(){
int k=12;
return(&k);
}
The output is 12 and a garbage value. Can somebody explain the output?
Shouldn't it return garbage values both times?
I know that k is local to fun(), so it would be stored on a stack and that it would be destroyed when fun() goes out of scope. What concept am I missing here?
Wouldn't it return garbage values both of the time?
After the return of fun, k does not exist anymore, so printing the value, stored in the address of k is undefined behaviour.
That's why you have different/garbage value.
k is local to fun(), so it would be stored on a stack and that activation would be destroyed when the fun ends, or am I missing some concept?
You're not missing anything, except the fact, that the stack isn't immediately "annulled", or something like this. In other words, after the return of fun, the compiler's free to do whatever it wants with this memory.
The stack isn't immediately cleared when a function returns, so the 12 will still be on the stack after fun() returns - until something else overwrites it.
You'll see different results in different compilers and different build options (debug vs. release).

Memory Allocation: Why this C program works? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Returning the address of local or temporary variable
The add function is implemented wrongly. It should return a value instead of a pointer.
Why aren't any errors when ans and *ans_ptr are printed and the program even gives correct result? I guess the variable of z is already out of scope and there should be segmentation fault.
#include <stdio.h>
int * add(int x, int y) {
int z = x + y;
int *ans_ptr = &z;
return ans_ptr;
}
int main() {
int ans = *(add(1, 2));
int *ans_ptr = add(1, 2);
printf("%d\n", *ans_ptr);
printf("%d\n", ans);
return 0;
}
The reason it 'works' is because you got lucky. Returning a pointer to a local variable is Undefined Behaviour!! You should NOT do it.
int * add(int x, int y) {
int z = x + y; //z is a local variable in this stack frame
int *ans_ptr = &z; // ans_ptr points to z
return ans_ptr;
}
// at return of function, z is destroyed, so what does ans_ptr point to? No one knows. UB results
Because C has no garbage collection, when the "z" variable goes out of scope, nothing happens to the actual memory. It is simply freed for another variable to overwrite if the compiler pleases.
Since no memory is allocated between calling "add" and printing, the value is still sitting in memory, and you can access it because you have its address. You "got lucky."
However, as Tony points out, you should NEVER do this. It will work some of the time, but as soon as your program gets more complex, you will start ending up with spurious values.
No. Your question displays a fundamental lack of understanding of how the C memory model works.
The value z is allocated at an address on the stack, in the frame which is created when control enters add(). ans_ptr is then set to this memory address and returned.
The space on the stack will be overwritten by the next function that is called, but remember that C never performs memory clean up unless explicitly told to (eg via a function like calloc()).
This means that the value in the memory location &z (from the just-vacated stack frame) is still intact in the immediately following statement, ie. the printf() statement in main().
You should never ever rely on this behaviour - as soon as you add additional code into the above it will likely break.
The answer is: this program works because you are fortunate, but it will take no time to betray, as the address you return is not reserved to you anymore and any one can use it again. Its like renting the room, making a duplicate key, releasing the room, and after you have released the room at some later time you try to enter it with a duplicate key. In this case if the room is empty and not rented to someone else then you are fortunate, otherwise it can land you in police custody (something bad), and if the lock of the room was changed you get a segfault, so you can't just trust on the duplicate key which you made without acquisition of the room.
The z is a local variable allocated in stack and its scope is as long as the particular call to the function block. You return the address of such a local variable. Once you return from the function, all the addresses local to the block (allocated in the function call stack frame) might be used for another call and be overwritten, therefore you might or might not get what you expect. Which is undefined behavior, and thus such operation is incorrect.
If you are getting correct output, then you are fortunate that the old value held by that memory location is not overwritten, but your program has access to the page in which the address lies, therefore you do not get a segmentation fault error.
A quick test shows, as the OP points out, that neither GCC 4.3 nor MSVC 10 provide any warnings. But the Clang Static Analyzer does:
ccc-analyzer -c foo.c
...
ANALYZE: foo.c add
foo.c:6:5: warning: Address of stack memory associated with local
variable 'z' returned to caller
return ans_ptr;
^ ~~~~~~~

Why y isn't dereferenced?

For the following code, this is how i understand:
Reference to pointer x is passed to function f,
val get the address of y which is a local variable.
So why, after exiting function f, x is ok? y should have been dereferenced.
x is equal to 5, and both printf print the same adress.
void f (int ** val)
{
int y = 5 ;
*val = & y;
printf("%d\n", &y);
}
int _tmain(int argc, _TCHAR* argv[])
{
int * x ;
f(&x );
if ( *x == 5 )
printf("%d", x);
}
It is Undefined Behaviour to access memory your program does not own.
The memory space occupied by y inside the function does not belong to your program once the function finishes, and yet you access it.
Anything could happen.
The worst thing to happen is for the program to behave as you expect.
When this happens, you believe it is ok to do what you did. IT IS NOT OK. Undefined Behaviour is bad.
Also it's not guaranteed that the same undefined behaviour happens on different runs of the program either. It can work as you expect for a while and crash when you demo it to the client (or your boss).
(Some good manifestations of UB are a crash, or lemon juice starting to ooze out of the USB port)
Anything can happen.
x is pointing to a local variable inside f which is no longer valid by the time f returns.
EDIT: Your post doesn't make it clear what you expect should happen, but as described much clearer in other answers, *x is pointing to memory which you do not own, and reading from *x is undefined behavior, so all bets are off. If you try to read from *x and it happens to be 5, it is probably because the value of 5 is still on the stack. Try to insert some calls to printf immediately after the call to f, and you will probably get another result.
The y variable sits on the stack. so you pass an address on the stack to x, and it's a valid address, but with undefined content. if you add another function (like printf) between the call to f and the check of *x == 5 you'll probably get a different result (since the stack was changed).
This is a classic...
The variable y is only alive as long as the function f is executed. Once it returns, the memory space occupied by y on the stack can be used for anything else.
y lives only within f(int**val), since it is declared in that scope.
Refering to its address outside of f() has no clear definition (or as we love to to say: Undefined Behaviour.
Because y might not be valid, but it's value is still in memory.
It'll get nasty if you call some other function or do something else which will write on it.
As nearly everyone has already said, it's undefined behavior. The reason you are printing the correct value (5) is because your program hasn't reused that memory, yet. Wait until your program puts something else at that address, then you will see incorrect results.

Resources