Stack execution in C [duplicate] - c

This question already has answers here:
What will be the value of uninitialized variable? [duplicate]
(6 answers)
Closed 4 years ago.
For the following code
#include <stdio.h>
void f() {
int x;
printf("x = %d\n", x);
}
void g() {
int y = 42;
printf("y = %d\n", y);
}
int main() {
f();
g();
return 0;
}
I get the following output
x = 22031
y = 42
If I change the order of the last two functions being executed in main() and run the code
void f() {
int x;
printf("x = %d\n", x);
}
void g() {
int y = 42;
printf("y = %d\n", y);
}
int main() {
g();
f();
return 0;
}
I get the following :
y = 42
x = 42
Can someone explain this to me please.I know it has to do with the way memory is allocated in addresses but I am not sure about the details.

x = 22031
y = 42
The X value is uninitialized stack garbage values. When your program is loaded into RAM it does not zero out stack or heap memory. Here is a reference for a C programs memory model.
The interesting case is when
y = 42
x = 42
So what is going on here? Well when you call the g function first, you pop values onto the stack (growing down in the memory model, or up if the memory model is different). The next time you call the f function the values of the uninitialized stack garbage has changed, to be what was assigned when you called g (assigning y's address to 42). This is because you have the same number of parameters and local variables pushed onto the stack in both functions, if you tweak them you will see different values. For example the following g definition may cause x to print 43 instead, depending on how the local variables get popped onto the stack.
void g() {
volatile int z = 43;
int y = 42;
printf("y = %d\n", y);
}
Make the compiler doesnt optimize it out "z" if you want to mess around with this.

You are seeing uninitialized values in memory from "something else" i.e. undefined behavior. When you run your program, you are getting and seeing "old" values in memory which come from something else than your program in your computer.
For example, the following program will experience undefined behavior because x is read before it is initialized and the value of x comes from another process:
#include <stdio.h>
int main() {
int x;
printf("x = %d\n", x);
return 0;
}

Related

Malloc() done on a variable passed by value in the arguments of a function

I wrote this code.
In the main you see x a pointer to an integer.
The function val allocates a storage space of an int , stores the value n in it and return the adress of the int allocated.
In the function val2 , i pass by value x , but when i execute val on x (x here is the copy of the original) inside the function val2 , i find that the value of *x in the main changes.
Isnt any change on the x inside the function val2 local ?
#include <stdio.h>
#include <stdlib.h>
int * val(int * x , int n)
{
int * d;
d = (int *)malloc(sizeof(int));
*d = n;
return (d);
}
void val2 (int * x ,int n)
{
x = NULL;
x = val(x , n);
}
int main()
{
int * x = NULL;
x = val (x , 2);
printf("\n after executing val \n");
printf(" The value of *x = %d\n" , *x);
printf("The adress x contains %p\n " ,x);
free(x);
val2(x , 7);
printf("\n after executing val2 \n");
printf(" The value of *x = %d\n" , *x);
printf("The adress x contains %p\n " ,x);
return 0;
}
I get *x = 2
The *x = 7
Can someone here expalin how *x changed in the context of the function and thanks y'all <3
Edit :
I copied this from the compiler :
after executing val
The value of *x = 2
The adress x contains 0xb6403068
after executing val2
The value of *x = 7
The adress x contains 0xb6403068
[Process completed - press Enter]
free(x) releases the memory pointed to by x. After that, the C implementation may use the memory for any other purpose.
When the main routine later uses that memory, by attempting to print *x, the behavior of the program is not defined by the C standard. Even using the value of a pointer after the memory it points to is freed results in the behavior not being defined by the C standard.
What likely happens is that, for the malloc in the call to val inside val2, the C implementation reuses the memory that was freed earlier. Thus, this call to val puts 7 in that memory. And then, in main, since x is still pointing to that memory (even though the C standard does not require this), accessing it with *x fetches the 7 from memory.
When the program is compiled with optimization or is compiled by another compiler or contains additional code that complicates the situation, this behavior is likely to change, because it is not behavior controlled by the C standard.
You explicitly said to replace 'x' with the return value from 'val'
x = val (x , 2);
'val' returns its 'd', so that overwrites mains 'x'

Why are the addresses of two variables in separate functions stored at the same address?

I have defined two functions foo1, foo2, and foo3 each function receives one argument (xval),(yval) and I also declared only one variable in each function (x),(y). why when printing x address, and y address. I find that the address is constant. And the same reason is given with xval, yval.
Here is the code:
#include <stdio.h>
void foo1(int xval) {
int x;
x = xval;
printf("X Address == 0x%x, Value of x == %d\n", &xval, x);
}
void foo2(int dummy) {
int y = dummy;
printf("Y Address == 0x%x, Value of y == %d\n", &dummy, y);
}
int main() {
foo1(7);
foo2(11);
return 0;
}
In foo1 and foo2 you are printing out the addresses of local variables (xval and dummy respectively) that are placed on the stack.
If I remember correctly, the C++ specification does not require these local variables to have different addresses. This should not concern you either.
The address of those variables has meaning only within the function in which the variable is defined, so comparing the addresses accross two different functions is meaningless.
What technically happens under the hood is, the compiler has placed 7 on the stack in your main() function before calling foo1(). Then foo1() prints out the address of that variable in the stack.
When foo1() is finished, the variable is popped from the stack and then 11 is placed on the stack before calling foo2(). This accidentally has used the same memory address but you should not count on this. For example, if you call foo2() from within foo1() this would affect the stack and the address would be different. Try the following:
#include <stdio.h>
extern void foo2(int dummy);
void foo1(int xval)
{
int x;
x = xval;
printf("X Address == 0x%x, Value of x == %d\n", &xval, x);
foo2(11);
}
void foo2(int dummy)
{
int y = dummy;
printf("Y Address == 0x%x, Value of y == %d\n", &dummy, y);
}
int main()
{
foo1(7);
return 0;
}
In summary, do not try to analyze what the concrete address value is. Simply use the address without looking into it. This is platform and compiler dependent.
xval and dummy are temporary variables. ("automatic variables" is the C term for them.) They're only guaranteed to exist while the function is executing. So there's no reason they couldn't be at the same address.
On your standard home computer, they would be found on the stack. Given they are both the first argument to the function, and given that the functions are called in sequence, I would be surprised if they didn't have the same address.
In fact, if you didn't take the address of the parameter, it's entirely possible for the argument to be passed to the function using a register so that no memory would be used at all.

What is the reason for the following output in C get changed dynamically [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 3 years ago.
Here is the code segment I am dealing with. It outputs 500, but I can not figure out, why this is happening.
#include<stdio.h>
int *f(int x){
int p;
p = x;
printf("p is : %d\n",p);
return &p;
}
int *g(int x){
int y;
y = x;
printf("p is : %d\n",y);
return &y;
}
int main(){
int *x,*y;
x = f(1000);
y = g(250);
*x = *x +250;
printf("%d %d\n",*x,*y);
return 0;
}
What is the reason for the output of 500?
Look at your function:
int *f(int x){
int p;
p = x;
printf("p is : %d\n",p);
return &p;
}
warning: address of local variable 'p' returned
[-Wreturn-local-addr]
Here variable p is created in the scope of f() after the return of function call this functions stack frame get destroyed so are everything in it, thus unexpected results.
You can either return the value directly or dynamically allocate memory using malloc(), in this case variable will be stored in heap instead of f() or particular functions stack later on you can free the memory when you're done.
You're returning the address of a local variable.
The lifetime of the variables p and y in the functions f and g ends when those functions return. As a result, the pointers to them become invalid and attempting to dereference them results in undefined behavior.
Rather than returning pointers, just return the value directly.

Passing double pointer to function [duplicate]

This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Closed 5 years ago.
I was trying out some pointer and function interaction and found out this behavior. The first printf prints 100 but the second printf prints 0!
Can somebody help me understand why?
void ptr_change (int **p)
{
int y = 100;
*p = &y;
}
int main ()
{
int x = 7;
int *p = &x;
ptr_change(&p);
printf("\nPtr = %d", *p);
printf("\nPtr = %d", *p);
return 0;
}
Compile:
gcc ptr2.c
Run and give output:
./a.out
Ptr = 100
Ptr = 0
y is an automatic local variable which will no longer exist after the function returns and you are assigning the address of an automatic local variable to the pointer.
In the main function you are dereferencing a pointer which no longer points to a valid location. This invokes undefined behavior. You can't expect anything good once there is undefined behavior of your code.
You return the address of an automatic variable from a procedure. The variable is no longer valid after the function returns. What happens next is called Undefined Behavior, however, an explanation for Intel machines and e.g. VC2008 is:
ptr_change(&p);
This places in p the address of the local variable y. After return from function ptr_change the stack space used by the function is released.
printf("\nPtr = %d", *p);
This first printf re-uses the stack space used earlier by ptr_change. It pushes 2 parameters onto the stack. The first parameter overwrites the stack space used by &p in your function call. y is not yet overwritten. The *p parameter of printf gets this value and pushes it onto the stack. The call to printf now overwrites int y.
printf("\nPtr = %d", *p);
As int y has been overwritten in the previous cal to printf, this call to printf prints garbage.
Note that any other form of undefined behavior is possible!
The value of y in
void ptr_change (int **p)
{
int y = 100;
*p = &y;
}
exists only temporary on stack as an automatic variable.
Once the function returns that location is not longer valid.
Compare the following program which passes pointer to the variable a and initializes pointer p.
#include<stdio.h>
void ptr_change2 (int **p, int *a)
{
*p = a;
}
int main ()
{
int x = 7;
int z = 8;
int *p = &x;
printf("\nPtr = %d", *p);
ptr_change2(&p,&z);
printf("\nPtr = %d", *p);
return 0;
}
Output:
Ptr = 7
Ptr = 8
*p = &y
is incorrect, you're assigning the address of y to the value of p.
try this instead:
p = &y
they will now have the same base address.
y = 100;
then print the pointer value of p
printf("%d", *p);

Change value in main using void sub-function

I am having trouble with this problem:
#include <stdio.h>
void change_number(int *x);
int main()
{
int x;
printf("Enter the number x: ")
scanf("%d", &x);
printf("In the main program: x = %d\n", x);
change_number(&x);
printf("In the main program: x = %d\n", x);
return 0;
}
void change_number(int *x)
{
x = *x+3;
printf("In the subroutine: x = %d\n", x);
}
Expected output:
Enter the number x: 555
In the main program: x = 555
In the subroutine: x = 558
In the main program: x = 558
Two notes:
I cannot modify main, or anything that comes before it. I can only modify the void change_number function, and the code inside it is my own code.
I cannot get the required output – my code only outputs x+3 in the subroutine, but doesn't change it in the main program.
How would I go about changing the value in the main routine? Please keep in mind that I am very new to C, and don't know many things yet (in fact, I just covered pointers yesterday).
The code
void change_number(int *x)
{
x = *x+3;
printf("In the subroutine: x = %d\n", x);
}
should read
void change_number(int *x)
{
*x = *x+3;
printf("In the subroutine: *x = %d\n", *x);
}
This will use the pointers as intended (you need to dereference them on the LHS as well)
I think an answer to the OP question needs a little bit explanation as C syntax may be confusing at times:
The function is declared as
void change_number(int *x)
The * means that the input parameter x is a pointer to a variable of type int. In other words x represents a location in memory.
Inside the function:
x is the address in memory of the int value
*x is the "content" of the memory address pointed by x
So, as other correctly pointed out, the function should be written as
void change_number(int *x)
{
*x = *x+3;
printf("In the subroutine: x = %d\n", *x);
}
Because as you act on *x you're acting on the content pointed by x
What is happening into main() ?
x is an int variable.
And you call:
change_number(&x);
The amplersand & means that you're not passing the value of x.
Instead you're passing a pointer to x, in other words the address in memory where the content of x is stored.
In other-other words x is passed by reference.
A final note: when writing a program in c (well, in any language, but expecially in c) the compiler warnings/errors and the debugger are your best friends.
Furthermore a good IDE will show you warnings as you type the code.
Anyway... the compiler should have warned you that
x = *x+3;
involves an implicit conversion from a int to int * (pointer to int) and most likely is a mistake.
You should use
*x = *x+3;
instead of
x = *x + 3;
What a function does with its parameters is, it makes a copy to work on and once the function's scope is ended, the copy is released which cannot change a value of a parameter passed to a function from outside.This is where pointers come in.
when passing a pointer to a function, think of it as a copy of the real address where in your case x is stored.
Thus in order to use x or change x, you have to use or change respectively *x(and it gets later dereferenced in the main program by &.
so like many others mentioned x = *x+3; should be *x = *x+3; and you'll get the desired results
Instead of printing in the change function you can also print in the main function by doing
*x=*x+3

Resources