1

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?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
  • http://ideone.com/e4Vyn : This is even more flattering ! –  Feb 03 '12 at 07:00
  • Run this program with Valgrind and examine the results. – Kos Feb 03 '12 at 07:02
  • I know I've seen this same topic many times here, but probably the most [well-known question on this topic](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) [has an answer with one of the all-time highest number of votes](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794). Even that question was marked as a dupe. – Dan Feb 03 '12 at 14:21

5 Answers5

2

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.

Duck
  • 26,924
  • 5
  • 64
  • 92
  • Ya I know that : But my question is that If r points to something which does not exist anymore :why do I get the output of the line r[0] as 3 ? –  Feb 03 '12 at 06:45
  • Because the stack is just a pointer that moves up and down. The information that was at that memory address remains there until something overwrites it. Add an intervening function that does something else and then try to print it out. It won't be 3 anymore. – Duck Feb 03 '12 at 06:49
  • 4
    @Rahul: You're lucky: [your bible was not taken](http://stackoverflow.com/a/6445794/46642). Now the real question is why do you steal hotel room keys? – R. Martinho Fernandes Feb 03 '12 at 06:51
1

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.

Ken Wayne VanderLinde
  • 18,915
  • 3
  • 47
  • 72
  • That's what I thought Initially : but this question was worth some point in a written test held by some company and I could not clear it :Even Undefined was not among the options :Was I luck to not get selected for such company ?! –  Feb 03 '12 at 06:52
  • 1
    That's interesting. "Undefined" or "implementation defined" (not sure which one - any C gurus?) would be the right answer. It could be that they assume the "simplest" stack semantics, in which your example would always result in 3. But if that the case, then the test is blatantly wrong. – Ken Wayne VanderLinde Feb 03 '12 at 06:56
  • @Rahul Rai - Are you sure you understood the question. Even if this was 100% reliable it seems like an incredibly odd question to ask. Effectively it is asking "Do you know what would result if you purposely do this thing you should never, ever do?" – Duck Feb 03 '12 at 07:14
  • Whatever : I have a collection of ugliest possible C question now : Thanks to Google/SE :: Can anyone tell me how to tackle these time eating ugly syntax seducing XX LEVEL idiosyncrasy of C questions? –  Feb 03 '12 at 07:29
1

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.
Lundin
  • 195,001
  • 40
  • 254
  • 396
0

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.

whtlnv
  • 2,109
  • 1
  • 25
  • 26
0

You can find pretty good answers here:

  1. can-a-local-variables-memory-be-accessed-outside-its-scope
  2. returning-the-address-of-local-or-temporary-variable
  3. return-reference-to-local-variable

Though the examples are for C++, underlying idea is same.

Community
  • 1
  • 1
dicaprio
  • 713
  • 2
  • 8
  • 25