1

Possible Duplicate:
Can a local variable's memory be accessed outside its scope?

What's the problem with the second printf?

#include<stdio.h>
int* fun() {
   int a =10;
   return &a;
}
int main() {
   int *a;
   a = fun();
   printf("%d",*a);
   printf("%d",*a);
   return 0;
}

I have returned the address of local variable and passed it to the printf. The first time it prints correctly as "10", but the second time it shows a junk value.

If initially a was a dangling pointer pointing to address of 10, why doesn't it the second time?

Can anyone explain this?

I even tried calling some other function before calling printf the first time but I still get the same output.

After BeniBela's ans i tried wit this..

#include<stdio.h>
int* fun()
{
int a =10;
return &a;
}
void fun2(int d)
{
int a,b,c;
}

int main()
{
int *a,b;
a = fun();
fun2(5);
printf("%d",*a);
printf("%d",*a);
return 0;
}

still same output..:(

Community
  • 1
  • 1
Charan Pai
  • 2,288
  • 5
  • 32
  • 44
  • I'm guessing English isn't your first language, but you might still want to consider running this through a spell checker - there are some pretty good ones available for most modern browsers. – Flexo Sep 06 '12 at 12:15
  • nope, i wanted to know how exactly the stack works..and y 1st time only it will print correctly... wat happens to the stack after printf() is called 1st time ? – Charan Pai Sep 06 '12 at 12:36
  • The `10` is also a junk value, it just happens to be the one you expected. If you try `printf("%d", rand());`, it will also sometimes print `10`. – Bo Persson Sep 06 '12 at 12:56

4 Answers4

9

There is no problem with printf, Your code has an Undefined Behavior.
You return the address of a variable local to the function, the lifetime of the variable is limited to the scope({,}) of the function, Once the scope of the function ends, the variable is longer in existence.The standard does not need the variable to exist anymore.

So your pointer refers to something that does not exist(though it might).Simply put, It is Undefined Behavior and you are at mercy of the compiler, It might show you any behavior and provide no explanation for the same.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • @KerrekSB: In all fairness If OP really knew so, then S/He wouldn't have asked the Q. – Alok Save Sep 06 '12 at 12:25
  • ya i am returning the address of local variable so m in mercy of compiler but my question is y it prints correctly only 1st time ? how stack operating der ? and even i tried calling some other function before calling printf() 1st time, still it shows same... – Charan Pai Sep 06 '12 at 12:39
  • 1
    @Als: Well, the way I understood it is that the OP wanted to use the specifics of the UB to get an insight into the inner workings of `printf`... – Kerrek SB Sep 06 '12 at 12:43
  • @KerrekSB: As I understand OPs comment above yours seeks an explanation for observed behavior after an Undefined Behavior has occurred. – Alok Save Sep 06 '12 at 14:54
3

What actually happens is:

All local variables are stored on the stack.

  1. Before the call to fun, the stack contains only the *a variable of main, like: |int *a = undefined||

  2. When fun is called, the parameters to fun (i.e. none), the address to main and the local variables of fun are added to the stack: |int *a = undefined| return to main | int a = 10 || (there is also the frame pointer but that doesn't matter)

  3. After fun returns, the stack is |int *a = 2nd next stack var|| return to main | int a = 10 |. The last 2 stack variables are invalid, but they are still there.

  4. When the first printf is called the parameters to printf (in inverse order *a then" %d"), the return address and the local variables of printf are added again after *a and override the old values:
    It first becomes |int *a = 2nd next stack var| int a = 10 || int a = 10 |
    then |int *a = 2nd next stack var| int a = 10 | "%d" |
    then |int *a = 2nd next stack var| int a = 10 | "%d" | return to main ||
    and finally |int *a = 2nd next stack var| int a = 10 | "%d" | return to main | local vars of printf ||

  5. When the second printf is called, *a still points to the second bin, but that one contains now "%d", which will appear as a strange number

[edit:]

The fun2 does not override the 10 on the stack, because gcc reserves empty bins on the stack, where the arguments of called functions are put. So it is not |int *a = 2nd next stack var| return to main | int a = 10 | as I wrote above, but more like |int *a = 4th next stack var | empty | empty | return to main | int a = 10 |.
When fun2 is called, it becomes |int *a = 4th next stack var | empty | 5 | return to main | int a = 10 |, and the 10 is still not overriden.

The int *a,b,c within the function do not matter, since they do not have a value assigned.

With gdb you can look at the actual stack (it grows backward):

Before fun:

0xffffd454:    0x080496f0    0xffffd488    0x080484eb    0x00000001
                 noise     (framepointer)  address      noise/empty bin     
                                           in main

After fun, before fun2 and its arguments:

0xffffd454:    0x0000000a    0xffffd488    0x08048441    0x00000001
                 a         (framepointer)   address     noise/empty bin     
                                            in main

After fun2:

0xffffd454:    0x0000000a    0xffffd488    0x08048451    0x00000005

                 a         (framepointer)   address       argument     
                                            in main       for fun2
BeniBela
  • 16,412
  • 4
  • 45
  • 52
1

Watch your warnings when compiling:

yourfile.c: In function ‘fun’:
yourfile.c:6:14: warning: function returns address of local variable [enabled by default]

This is a problem of scope, the variable "a" has a local scope within the "fun" function. Meaning when you try to access the address of that local variable from main (outside its scope) it's no longer valid. If you want to fix this you can make the variable global, (but change the name!) then you'll see the code working as you expect:

int b;

int* fun() 
{  
  b = 10;
  return &b; 
} 

int main() 
{ 
  int *a; 
  a = fun(); 
  printf("%d",*a); 
  printf("%d",*a);
  getc(stdin);
  return 0; 
}

Output:

> 1010
Mike
  • 47,263
  • 29
  • 113
  • 177
0

You return the address of an object that is created within the function, thus might not be valid anymore after termination of the function. Create a pointer instead!

mmoment
  • 1,269
  • 14
  • 30
  • 1
    "might not be valid" is inaccurate. It is not legal to use, no matter what. The fact that sometimes you "get away with it" means nothing. – Flexo Sep 06 '12 at 12:17