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);
Related
I was studying for a test with the following question with the given output :
#include <stdio.h>
int main()
{
int i = 10;
int *const p = &i;
foo(&p);
printf("%d\n", *p);
}
void foo(int **p)
{
int j = 11;
*p = &j;
printf("%d\n", **p);
}
Output : 11 11
I understand that the address of *p pointing to int i is passed to the function foo. Here, **p is a pointer pointing to *p, where *p points to int i.
In the function, **p pointer changes and points to int j, and the first printf is called and 11 is printed.
What I don't understand is the output from the 2nd printf function. Why is it printing 11, when it should be 10? I've checked and the value of int i and it did not change, so shouldn't dereferencing *p give 10 and not 11.
Can someone explain to me the logic behind what is happening and why is it happening?
First you asign p the address of i and you input the address of p to the function foo and inside the foo function the the value of p becomes what every the value in j (*p = &j). When the memory address changes in the foo function you are not changing it back.
NOTE: There the variable p is not passed by value, It is passed to the function by reference. So any change you do to the p variable inside the foo function will affect the p variable inside the main function because they have the same memory address
The line:
*p = &j;
makes the original variable
int *const p
point to the address of the local variable
int j
After foo is called, that local variable j has since been deallocated from the stack, but p is still pointing to that same stack location which still has that value of 11. So you are illegally accessing deallocated stack memory but it just happens to remain the value of 11. So it is printed a second time.
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.
I am trying to initialize the integer pointer "p" inside the "init_pointer" function. After the function returns I am printing the pointer and the dereferenced value twice. The first dereference prints the expected value 100, but the second dereference prints random values.
#include<stdio.h>
void init_pointer(int d, int **c){
(*c) = &d;
}
int main(){
int x = 100;
int *p;
init_pointer(x,&p);
printf("pointer = %p, value = %d\n",p,*p);
printf("pointer = %p, value = %d\n",p,*p);
return 0;
}
Output:
pointer = 0x7fffb4d4b9ac, value = 100
pointer = 0x7fffb4d4b9ac, value = 32567
The function has copied the value to a new local variable in init_pointer(int d, int **c)
d is local to init_pointer which was passed by main from x. Both x and d are separate variables whose addresses are different. Accessing the address of d outside init_pointer will lead to Undefined Behavior.
It would not make sense to call the function like this but this will work:
void init_pointer(int *d, int **c)
{
(*c) = d;
}
int main()
{
int x = 100;
int *p;
init_pointer(&x,&p);
printf("pointer = %p, value = %d\n",p,*p);
printf("pointer = %p, value = %d\n",p,*p);
return 0;
}
Output:
pointer = 0xbfde132c, value = 100
pointer = 0xbfde132c, value = 100
void init_pointer(int d, int **c){
(*c) = &d;
}
Here *c points to a local copy inside init_pointer(). Once init_pointer() returns, the address becomes invalid, and p in main() points to a freed address.
In init_pointer you assign the address of the parameter d to *c. The address of the parameter is a stack address.
In the first call to printf, the stack (although deallocated) is still intact, so p points to the discarded parameter d on the stack, which still has a value of 100, and *p is pushed first onto the stack.
In the second call to printf, the first call has overwritten the stack. Although the pointer still points to the same address, its value there has been overwritten by the push of p. Hence p (an address) is printed.
Notes: with "the stack (although deallocated)" I mean the stack of and below sp (intel; growing downward). Also, the stack can have been overwritten at any time, e.g. when interrupts occur.
#include<stdio.h>
int q = 10;
void fun(int *p){
*p = 15;
p = &q;
printf("%d ",*p);
}
int main(){
int r = 20;
int *p = &r;
fun(p);
printf("%d", *p);
return 0;
}
I was playing with pointers. Could not understand the output of this.
Output is coming as 10 15.
Once p is pointing to address of q, why on returning to main function it's value changes? Also why it changed to the value '15' which was assigned to it in the function before '10'.
Because p is fun() is not the same p in main(). p , in each function, is local. So changing one doesn't affect other.
In C, all function parameters are passed by value, including pointers.
*p = 15; will set r to 15 as *p is pointing to the memory occupied by r in main() prior to its reassignment to &q;
Your reassignment p = &q; does not change what p points to in the caller main(). To do that, you'd need to doubly indirect the pointer, i.e. change the function prototype to void fun(int **p){, call it using fun(&p);, and reassign using *p = &q;.
Two steps:
First call to fun(), assigning the address of global int q [holding value 10] to p inside the fucntion scope and printing it. The first output ==> 10;
Once the call returns from fun(), it will hold the previous address, [passed from main()] and hence, will print the value held by that address [which is 15, modified inside fun()].
#include <stdio.h>
int main()
{
int i = 10;
int *p = &i;
foo(&p);
printf("%d ", *p);
printf("%d ", *p);
}
void foo(int **const p)
{
int j = 11;
*p = &j;
printf("%d ", **p);
}
What wii be the final output
Why Third printf will print undefined value ?
Within foo, you assign a value to *p which points to a location on the stack that's been allocated to foo. When foo returns, the stack is popped, and that location is free for reuse — but the p in main still points to it.
When you call printf in main the first time, it happens that that that location on the stack hasn't (yet) had any new data written to it, and so reading *p gives you 11, and you push that on the stack along with some other things for the call to printf, and it succeeds in printing 11. But the action of calling printf changes the data on the stack, including (potentially) the location that p (in main) points to, because the stack was popped after foo returned.
The second call then uses the data from that stack location again, which may have been changed by the first call to printf.
Moral of the story: Don't keep pointers to stack locations that have been popped.
the "i" in foo is stack-allocated, every thing will work fine until it goes off from the memory, so printf of foo will work fine,while the second printf and the third printf will work until the integer i of foo goes off from the memory. This is a system issue, it has the probability that the 2 last printf's work or don't work. If you wanna them work all the time you need to heap-allocate integer i of foo using mallo
Third printf is printing the right value. The problem is that j is an automatic local variable and it is no longer exist once function return. Therefore, p in main is not pointing to the place you are expecting and ultimately your program invokes undefined behaviour.
Possible solutions:
1. Use static keyword in the declaration of j
void foo(int **const p)
{
static int j = 11;
*p = &j;
printf("%d ", **p);
}
2. Dynamically allocate j
void foo(int **const p)
{
int *j = malloc(sizeof(int));
*j = 11;
*p = j;
printf("%d ", **p);
}
When void foo() is called ,new stack frame gets created on stack so int j = 11; being a local variable goes into this stack frame . So say int j is at address 0x000ffd with value 10 so your *p now stores this address . Now what happens when this function returns stack unwinds
During Stack Unwinding , it does all the work of cleanup. so all data which is into that stack frame gets destroyed so now that address 0x000ffd might have same value or something different but variable j is not associated to it now. So its undefined behavior