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;
^ ~~~~~~~
Related
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.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
How to access a local variable from a different function using pointers?
(10 answers)
Closed 4 years ago.
#include <stdio.h>
int* function1(void);
int main()
{
int x = 10;
int *p = function1();
printf("%d\n", *p);
printf("%d\n", p);
}
int* function1(void)
{
int z;
z = 20;
z++;
return &z;
}
Variable 'z' is local to the 'function1', and is not alive after the
'function1' is terminated.
Now to access the value at the memory space of the variable 'z', its
address is returned by the function.
So, even after the termination, will the memory space of the variable
'z' will still be reserved, as the pointer accesses the variable?, in such case what will be the properties of the memory space?
Or What if some-other variable is allocated with the same memory space
of variable 'z'?
Note: GCC compiler of code blocks has compiled the program successfully, without any error and warning.
In general what you do is undefined.
However, on Intel architectures z is on the stack and after return, if you don't call any other function the value will probably still be available because the memory has not yet been reused. As soon as you call another function, the memory will probably be overwritten and so will contain garbage for you.
In general: Don't do this!
The variable z does no longer exist after the function function1 finishes it's execution. In function main you are trying to reference a memory address which has been deallocated after the function's call. This will cause undefined behavior.
When the function call happens, all your local variables will be in stack. During function call, the stack variables can be modified. When the function call returns, the stack pointer is decremented’
Hence, you will be accessing something which is not guaranteed in any way. In programming languages, this is addressed as a case of undefined behaviour, since you are overriding the rules of programming language.
In this case of function, given that you stack frame is still active and not modified by any other code, you might get the same value that you wrote to that address.
But is not guaranteed in anyway and dont assume anything not guaranteed.
I came across this page that illustrates common ways in which dangling pointes are created.
The code below is used to illustrate dangling pointers by returning address of a local variable:
// The pointer pointing to local variable becomes
// dangling when local variable is static.
#include<stdio.h>
int *fun()
{
// x is local variable and goes out of scope
// after an execution of fun() is over.
int x = 5;
return &x;
}
// Driver Code
int main()
{
int *p = fun();
fflush(stdout);
// p points to something which is not valid anymore
printf("%d", *p);
return 0;
}
On running this, this is the compiler warning I get (as expected):
In function 'fun':
12:2: warning: function returns address of local variable [-Wreturn-local-addr]
return &x;
^
And this is the output I get (good so far):
32743
However, when I comment out the fflush(stdout) line, this is the output I get (with the same compiler warning):
5
What is the reason for this behaviour? How exactly is the presence/absence of the fflush command causing this behaviour change?
Returning a pointer to an object on the stack is bad, as you've mentioned. The reason you only see a problem with your fflush() call in place is that the stack is unmodified if it's not there. That is, the 5 is still in place, so the pointer dereference still gives that 5 to you. If you call a function (almost any function, probably) in between fun and printf, it will almost certainly overwrite that stack location, making the later dereference return whatever junk that function happened to leave there.
This is because calling fflush(stdout) writes onto the stack where x was.
Let me explain. The stack in assembly language (which is what all programming languages eventually run as in one way or another) is commonly used to store local variables, return addresses, and function parameters. When a function is called, it pushes these things onto the stack:
the address of where to continue executing code once the function completes.
the parameters to the function, in an order determined by the calling convention used.
the local variables that the function uses.
These things are then popped off of the stack, one by one, simply by changing where the CPU thinks the top of the stack is. This means the data still exists, but it's not guaranteed to continue to exist.
Calling another function after fun() overwrites the previous values above the top of the stack, in this case with the value of stdout, and so the pointer's referenced value changes.
Without calling another function, the data stays there and is still valid when the pointer is dereferenced.
#include<stdio.h>
int * fun(int a1,int b)
{
int a[2];
a[0]=a1;
a[1]=b;
return a;
}
int main()
{
int *r=fun(3,5);
printf("%d\n",*r);
printf("%d\n",*r);
}
Output after running the code:
3
-1073855580
I understand that a[2] is local to fun() but why value is getting changed of same pointer?
The variable a is indeed local to fun. When you return from that function, the stack is popped. The memory itself remains unchanged (for the moment). When you dereference r the first time, the memory is what you'd expect it to be. And since the dereference happens before the call to printf, nothing bad happens. When printf executes, it modifies the stack and the value is wiped out. The second time through you're seeing whatever value happened to be put there by printf the first time through.
The order of events for a "normal" calling convention (I know, I know -- no such thing):
Dereference r (the first time through, this is what it should be)
Push value onto stack (notice this is making a copy of the value) (may wipe out a)
Push other parameters on to stack (order is usually right to left, IIRC) (may wipe out a)
Allocate room for return value on stack (may wipe out a)
Call printf
Push local printf variables onto stack (may wipe out a)
Do your thang
Return from function
If you change int a[2]; to static int a[2]; this will alleviate the problem.
Because r points to a location on the stack that is likely to be overwritten by a function call.
In this case, it's the first call to printf itself which is changing that location.
In detail, the return from fun has that particular location being preserved simply because nothing has overwritten it yet.
The *r is then evaluated (as 3) and passed to printf to be printed. The actual call to printf changes the contents of that location (since it uses the memory for its own stack frame), but the value has already been extracted at that point so it's safe.
On the subsequent call, *r has the different value, changed by the first call. That's why it's different in this case.
Of course, this is just the likely explanation. In reality, anything could be happening since what you've coded up there is undefined behaviour. Once you do that, all bets are off.
As you've mentioned, a[2] is local to fun(); meaning it is created on the stack right before the code within fun() starts executing. When fun exits the stack is popped, meaning it is unwound so that the stack pointer is pointing to where it was before fun started executing.
The compiler is now free to stick whatever it wants into those locations that were unwound. So, it is possible that the first location of a was skipped for a variety of reasons. Maybe it now represents an uninitialized variable. Maybe it was for memory alignment of another variable. Simple answer is, by returning a pointer to a local variable from a function, and then de-referencing that pointer, you're invoking undefined behavior and anything can happen, including demons flying out of your nose.
When you compile you code with the following command:
$ gcc -Wall yourProgram.c
It will yield a warning, which says.
In function ‘fun’:
warning: function returns address of local variable
When r is dereferenced in first printf statement, it's okay as the memory is preserved. However, the second printf statement overwrites the stack and so we get an undesired result.
Because printf is using the stack location and changes it after printing the first value.
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.