4

Here is my code:

#include <stdio.h>
//returning a pointer
int *fun()
{
    int i = 10;
    //printf ("%u\n",i);
    //printf ("%u\n",&i);
    return &i;
}
int main()
{
    int *p;
    p = fun();
    printf ("p = %u\n", p);
    printf ("i = %u \n",*p);
    return 0;
}

If I remove the comments in the function fun, then the second printf in main shows 10 as the output. otherwise it shows a garbage value. any idea?

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
whizvids
  • 248
  • 2
  • 8
  • 13
    And what you want to know is what? `i` is located on the stack so when the function returns `&i` the memory location of `i` becomes invalid. I think you want to say: `int* i = malloc( sizeof( int ) ); *i = 10; return i;` – clcto Oct 14 '13 at 21:01
  • 2
    Also in your printf format string, you're passing %u, which means unsigned, but giving it an int, which is signed -- undefined behavior will result. – scott_fakename Oct 14 '13 at 21:06
  • i understand why *p shows garbage value, what i dont understand is why does uncommenting the printfs in the function fun, causes second printf in main to print the correct output 10..! – whizvids Oct 14 '13 at 21:09
  • Or declare it as `static int i = 10;` – David Ranieri Oct 14 '13 at 21:09
  • returning address of local results in undefined behavior. undefined behavior means that the compiler can do whatever it likes. If you have a really evil compiler then your code will work fine for years and then fail at your largest customer in the middle of the night – pm100 Oct 14 '13 at 23:30
  • and so always compile with -wall -werror , -pedantic is optional – pm100 Oct 14 '13 at 23:31

3 Answers3

3

Without the commented lines i is never used. So depending on your optimizer, i may never even be allocated. When you add printf within the function, the variable is now used so the compiler allocates memory for i on the stack frame (which happens to have not been reclaimed at the point your second set of printfs occurs). Of course, you cannot depend on when that memory will be reclaimed- but the next function call that occurs is very likely to overwrite the fun() stack frame.

If you set your compiler to disable code optimization you may have a different result. Or you can try setting the variable to volatile which tells the compiler that it doesn't know about all uses of the variable and so allocate it even if the optimizer says it's not needed (which won't stop your variable's memory from being deallocated after you leave the function, it'll just force the allocation in the first place).

As a side note this issue can come up in embedded systems where you have a pointer to a hardware register that triggers hardware actions when set (for instance you might have hardware registers that control a robots arm motion). If you don't declare the pointer to that register volatile then the compiler may optimize away your assignment thinking it's never used.

KayakDave
  • 24,636
  • 3
  • 65
  • 68
0

When fun returns, i goes out of scope so that the address you've returned now points to something else. Try to malloc() some memory and return that instead. And don't forget to call free() when you're done with it :)

And also the second printf in main shows 10 is a pure luck because you have not yet used that space/address for something else.

Mihail Shishkov
  • 14,129
  • 7
  • 48
  • 59
0

As @clcto mentions in the first comment the variable i is local to function and it get de-allocated when function returns.

Now why uncommenting the two print statements in function fun() make the value of p to be 10?
It can be because of many reasons which may be dependent on internal behavior of C and your system. But my guess is that it is happening because of how print works.
It maintains a buffer that I know. It fills it and then print it to the console when it get filled completely. So the first two print calls in fun() push i to the buffer, which is not yet filled completely. So when you are returning from fun() it may be possible that i doesn't get de-allocated because buffer is using it (or may be any other reason which I am not sure of but due to buffer i is preserved.)

To support my guess I tried to flush the buffer before printing again and now it doesn't prints 10. You can see the output here and the modified code is below:

#include <stdio.h>
//returning a pointer
int *fun()
{
    int i = 10;
    printf ("%u\n",i);
    printf ("%u\n",&i);
    return &i;
}
int main()
{
    int *p;
    p = fun();
    fflush(stdout);
    printf ("p = %u\n", p);
    printf ("i = %u \n",*p);
    return 0;
}

I think my guess is wrong, as @KayakDave pinted out. It just get fit to the situation completely. Kindly refere to his answer for correct explanation.

Community
  • 1
  • 1
Abhishek Gupta
  • 6,465
  • 10
  • 50
  • 82
  • 1
    The flush() call creates a new stack frame which is overwriting the one used by fun() out. And that's likely why i stops printing. – KayakDave Oct 14 '13 at 21:40