Array Destruction At The End Of Function Call - c

Here is my code
#include<stdio.h>
int * fun(int a1,int b)
{
int a[2];
a[0]=a1;
a[1]=b;
//int c=5;
printf("%x\n",&a[0]);
return a;
}
int main()
{
int *r=fun(3,5);
printf("%d\n",r[0]);
printf("%d\n",r[0]);
}
I am running codeblocks on Windows 7
Every time I run the loop I get the outputs as
22fee8
3
2293700
Here is the part I do not understand :
r expects a pointer to a part of memory which is interpreted as a sequence of boxes (each box of 4 byte width - >Integers ) on invoking fun function
What should happen is printf of function will print the address of a or address of a[0]:
Seconded
NOW THE QUESTION IS :
each time I run the program I get the same address?
And the array a should be destroyed at the end of Function fun only pointer must remain after function call
Then why on earth does the line r[0] must print 3?

r is pointing to something that doesn't exist anymore. You are returning a pointer to something on the stack. That stack will rewind when fun() ends. It can point to anything after that but nothing has overwritten it because another function is never called.

Nothing forces r[0] to be 3 - it's just a result of going for the simplest acceptable behaviour.
Basically, you're right that a must be destroyed at the end of fun. All this means is that the returned pointer (r in your case) is completely unreliable. That is, even though r[0] == 3 for you on your particular machine with your particular compiler, there's no guarantee that this will always hold on every machine.
To understand why it is so consistent for you, think about this: what does is mean for a to be destroyed? Only that you can't use it in any reliable way. The simplest way of satisfying this simple requirement is for the stack pointer to move back to the point where fun was called. So when you use r[0], the values of a are still present, but they are junk data - you can't count on them existing.

This is what happens:
int a[2]; is allocated on the stack (or similar). Suppose it gets allocated at the stack at address 0x12345678.
Various data gets pushed on the stack at this address, as the array is filled. Everything works as expected.
The address 0x12345678 pointing at the stack gets returned. (Ironically, the address itself likely gets returned on the stack.)
The memory allocated on the stack for a ceases to be valid. For now the two int values still sit at the given address in RAM, containing the values assigned to them. But the stack pointer isn't reserving those cells, nor is anything else in the program keeping track of that data. Computers don't delete data by erasing the value etc, they delete cells by forgetting that anything of use is stored at that memory location.
When the function ends, those memory cells are free to be used for the rest of the program. For example, a value returned by the function might end up there instead.
The function returned a pointer to a segment on the stack where there used to be valid data. The pointer is still 0x12345678 but at that address, anything might be stored by now. Furthermore, the contents at that address may change as different items are pushed/popped from the stack.
Printing the contents of that address will therefore give random results. Or it could print the same garbage value each time the program is executed. In fact it isn't guaranteed to print anything at all: printing the contents of an invalid memory cell is undefined behavior in C. The program could even crash when you attempt it.

r is undefined after the stack of the function int * fun(int a1,int b) is released, right after it ends, so it can be 3 or 42 or whatever value. The fact that it still contains your expected value is because it haven't been used for anything else, as a chunk of your memory is reserved for your program and your program does not use the stack further. Then after the first 3 is printed you get another value, that means that stack was used for something else, you could blame printf() since it's the only thing runing and it does a LOT of things to get that numbers into the console.
Why does it always print the same results? Because you always do the same process, there's no magic in it. But there's no guarantee that it'll be 3 since that 'memory space' is not yours and you are only 'peeking' into it.
Also, check the optimization level of your compiler fun() and main(), being as simple as they are, could be inline'd or replaced if the binary is to be optimized reducing the 'randomness' expected in your results. Although I wouldn't expect it to change much either.

You can find pretty good answers here:
can-a-local-variables-memory-be-accessed-outside-its-scope
returning-the-address-of-local-or-temporary-variable
return-reference-to-local-variable
Though the examples are for C++, underlying idea is same.

Related

(nil) value returned by int pointer in c

when we declare a pointer it points to some random location or address in memory unless we explicitly assign a particular value(address of any variable) to it.
Here is code:
int *p;
printf("int is %p\n",p);
float *j;
printf("float is %p\n",j);
double *dp;
printf("double is %p\n",dp);
char *ch ;
printf("char is %p\n",ch);
j=(float *)p;
printf("cast int to float %p\n",j);
output:
int is (nil)
float is 0x400460
double is 0x7fff9f0f1a20
char is (nil)
cast int to float (nil)
Rather than printing the random location it prints (nil)
what is (nil) here ?? I don't understand the behaviour of pointers here??
Uninitialized pointer variables don't point to random address. Where they point is undefined.
In practice, they have the value what's left in the stack, which you can't know for sure. In your example, those several pointers happens to have 0 values, so they happen to be null pointer, and they print as nil.
Don't rely on such behavior, ever.
If by the "gnu" tag you mean that you're using glibc, then the reason is that the printf implementation in glibc will print "(nil)" when encountering a NULL pointer.
In other words, several of your pointers happen to have the value NULL (0), because that's what happened to be on the stack at that particular location.
Elaborating on what #yu hao has said:
Whenever a subroutine is invoked, a stack frame is allocated to the subroutine. This frame exists until return statement is encountered.
A subroutine frequently needs memory space for storing the values of local variables, the variables that are known only within the active subroutine and do not retain values after it returns. For doing so , the compiler allocate space for this use by simply moving the top of the stack by enough to provide the space. This is very fast when compared to dynamic memory allocation, which uses the heap space. Note that each separate activation of a subroutine gets its own separate space in the stack for locals known as Stack Frames.
The main reason for doing this is to keep track of the point to which each active subroutine should return control when it finishes executing. An active subroutine is one that has been called but is yet to complete execution after which control should be handed back to the point of call. Such activations of subroutines may be nested to any level (recursive as a special case), hence the stack structure. If, for example, a subroutine DrawSquare calls a subroutine DrawLine from four different places, DrawLine must know where to return when its execution completes. To accomplish this, the address following the call instruction, the return address, is also pushed onto the call stack with each call.
Coming back to your question, during its execution , the function can make changes to its stack frame and When a function 'returns', its frame is 'popped' from stack.
But the contents of stack remains unchanged in this process. Only the stack pointer gets modified to point to previous frame. So when a new subroutine gets called, new frame is allocated on top of previous one,and if the subroutine has uninitialized variables, they will print value that is stored in the memory allocated to them . Which will depend on the state of stack at that point of time.
All of your pointers are nil/ undefiend or the are just random values from the stack!
See: http://ideone.com/wwiy8F

Call Stack - while a function returns reference of local variable to the calling function which is followed by the call to another function

#include<stdio.h>
int *fun();
int main()
{
int *ptr;
ptr=fun();
printf("%d",*ptr);
printf("%d",*ptr);
}
int * fun()
{
int k=4;//If auto then cannot print it two times.....stack will be changed
return(&k);
}
O/P: 4
-2
Calling printf() for the first time prints the correct value.
Calling any function (even printf( ) ) immediately after the call to fun( ). This time printf( ) prints a garbage value. Why does this happen?Why do we not get a garbage value during the first print statement itself????
This is not behavior you can rely on; it may and likely will differ on different systems, even different versions of the compiler or different compiler switches.
Given that, what is likely happening is this: fun returns a pointer to where it stored k. That part of the stack is no longer reliable, because the function that allocated it has exited. Nonetheless, nobody has written over it yet, so the 4 is still where it was written. Then main prepares to call printf. To do so, it gets the first argument, *ptr. To do this, it loads from the place ptr points, which is the (former) address of k, so the load gets the 4 that is there. This 4 is stored in a register or stack location to be passed to printf. Then the address of the format string, "%d", is stored to be passed to printf. Then printf is called. At this point, printf uses a great deal of stack and writes new data where k used to be. However, the 4 that was passed as an argument is in a safe place, where arguments to printf should be, so printf prints it. Then printf returns. Then the main routine prepares to call printf again. This time, when it loads from where ptr points, the 4 is no longer there; it is some value that was written during the first call to printf. So that value is what is passed to printf and is what is printed.
Never write code that uses this behavior. It is not reliable, and it is not proper code.
Why does it surprise you? The behavior is undefined, but there's nothing unusual in observing what you observed.
All variables live somewhere in memory. When a variable gets formally destroyed (like local variables when function exits) the memory it used to occupy still exists and, most likely, still holds the last value that was written to it. That memory in now officially free, but it will continue to hold that last value until some other code reuses that memory for other purposes and overwrites it.
This is what you observe in your experiment. Even though the variable kno longer exists, pointer ptr still points to its former location. And that former location still happens to hold the last value of k, which is 4.
The very first printf "successfully" receives a copy of that value for printing. And that very first printf is actually the one that reuses the old memory location and overwrites the former value of k. All further attempts to dereference ptr will show that 4 is no longer there, which is why your second printf prints something else.
Variable k is local to fun(), means it will be destroyed when the function returns. This is a very bad coding technique and will always lead to problem.
And the reason why the first printf returns the correct value:
First of all it might or might not return the value. The thing is suppose k is written somewhere on stack memory. First time when the function returns printf might get the correct value because that part of memory might exist for a while. But this is not guaranteed.

puzzled with the output

why does printf prints 7 although the variable a was local to the function fun() and should no longer exist once the control returns from function fun().
Here is the c code
‎#include<stdio.h>
main()
{
int *fun();
int *c=fun();
printf("%d",*c);
getch();
}
int *fun()
{
int a=7;
return(&a);
}
output : 7
This is because even if the variable does not exist anymore, the memory location where it was has not yet been used for something else. Hence, the pointer still points to a memory location where the bits contains an int with value 7.
But this is definitely undefined behavior. You should not rely on it.
There is a difference between the language idioms and the physical operation of the hardware. In "C" words, yes, your variable should not be accessed anymore, but physically the variable a has been allocated on the stack of your program, which is not erased each time a function returns (it would take too much time), thus you can still read it.
Anyway, this is not recommended because other function calls may erase this data.
once the fun() return, the frame pointer has been set back to point the main() frame again. the pointer c pointed to some address in the memory, since the fun() has already returned, we don't know what's in the adress,but if nothing else has been written to the adress, it can still be the previous variable a. the C standard simply move the frame pointer when a function returns.
I think its because you are printing *c , which displays the value which is stored on the location i.e &a , just try to print c then you will get the address of 7 .
It is because the address is already passed to the variable c and the memory address can be read outside the function as well

Explain the output

#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.

How does temporary storage work in C when a function returns?

I know C pretty well, however I'm confused of how temporary storage works.
Like when a function returns, all the allocation happened inside that function is freed (from the stack or however the implementation decides to do this).
For example:
void f() {
int a = 5;
} // a's value doesn't exist anymore
However we can use the return keyword to transfer some data to the outside world:
int f() {
int a = 5;
return a;
} // a's value exists because it's transfered to the outside world
Please stop me if any of this is wrong.
Now here's the weird thing, when you do this with arrays, it doesn't work.
int []f() {
int a[1] = {5};
return a;
} // a's value doesn't exist. WHY?
I know arrays are only accessible by pointers, and you can't pass arrays around like another data structure without using pointers. Is this the reason you can't return arrays and use them in the outside world? Because they're only accessible by pointers?
I know I could be using dynamic allocation to keep the data to the outside world, but my question is about temporary allocation.
Thanks!
When you return something, its value is copied. a does not exist outside the function in your second example; it's value does. (It exists as an rvalue.)
In your last example, you implicitly convert the array a to an int*, and that copy is returned. a's lifetime ends, and you're pointing at garbage.
No variable lives outside its scope, ever.
In the first example the data is copied and returned to the calling function, however the second returns a pointer so the pointer is copied and returned, however the data that is pointed to is cleaned up.
In implementations of C I use (primarily for embedded 8/16-bit microcontrollers), space is allocated for the return value in the stack when the function is called.
Before calling the function, assume the stack is this (the lines could represent various lengths, but are all fixed):
[whatever]
...
When the routine is called (e.g. sometype myFunc(arg1,arg2)), C throws the parameters for the function (arguments and space for the return value, which are all of fixed length) on to the stack, followed by the return address to continue code execution from, and possibly backs up some processor registers.
[myFunc local variables...]
[return address after myFunc is done]
[myFunc argument 1]
[myFunc argument 2]
[myFunc return value]
[whatever]
...
By the time the function fully completes and returns to the code it was called from, all of it's variables have been deallocated off the stack (they might still be there in theory, but there is no guarantee)
In any case, in order to return the array, you would need to allocate space for it somewhere else, then return the address to the 0th element.
Some compilers will store return values in temporary registers of the processor rather than using the stack, but it's rare (only seen it on some AVR compilers).
When you attempt to return a locally allocated array like that, the calling function gets a pointer to where the array used to live on the stack. This can make for some spectacularly gruesome crashes, when later on, something else writes to the array, and clobbers a stack frame .. which may not manifest itself until much later, if the corrupted frame is deep in the calling sequence. The maddening this with debugging this type of error is that real error (returning a local array) can make some other, absolutely perfect function blow up.
You still return a memory address, you can try to check its value, but the contents its pointing are not valid beyond the scope of function,so dont confuse value with reference.
int []f() {
int a[1] = {5};
return a;
} // a's value doesn't exist. WHY?
First, the compiler wouldn't know what size of array to return. I just got syntax errors when I used your code, but with a typedef I was able to get an error that said that functions can't return arrays, which I knew.
typedef int ia[1];
ia h(void) {
ia a = 5;
return a;
}
Secondly, you can't do that anyway. You also can't do
int a[1] = {4};
int b[1];
b = a; // Here both a and b are interpreted as pointer literals or pointer arithmatic
While you don't write it out like that, and the compiler really wouldn't even have to generate any code for it this operation would have to happen semantically for this to be possible so that a new variable name could be used to refer the value that was returned by the function. If you enclosed it in a struct then the compiler would be just fine with copying the data.
Also, outside of the declaration and sizeof statements (and possibly typeof operations if the compiler has that extension) whenever an array name appears in code it is thought of by the compiler as either a pointer literal or as a chunk of pointer arithmetic that results in a pointer. This means that the return statement would end looking like you were returning the wrong type -- a pointer rather than an array.
If you want to know why this can't be done -- it just can't. A compiler could implicitly think about the array as though it were in a struct and make it happen, but that's just not how the C standard says it is to be done.

Resources