0

I was writing a program and facing this problem that the following function used to return garbage values:

int* foo(int temp){
   int x = temp;
   return &x;
}

When I modified it to this, it worked fine:

int* foo(int *temp){
    int *x = temp;
    return x
}

What was wrong with the first version?

pb2q
  • 58,613
  • 19
  • 146
  • 147
h4ck3d
  • 6,134
  • 15
  • 51
  • 74
  • 1
    I'm not sure about a C-tagged one, but the story is pretty amusing and it's the same problem: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope – chris Aug 20 '12 at 17:55

2 Answers2

7

The first version returns a reference to a local variable x whose storage is limited to the function foo. When the function exits, x can no longer be used. Returning a reference to it is one instance of a dangling pointer.

In the second version, you're really only passing in and returning the same pointer value, which refers to memory which isn't limited by the lifetime of the function. So even after the function exits, the returned address is still valid.

Another alternative:

int *foo(int temp)
{
    int *x = malloc(sizeof(int));
    *x = temp;
    return x;
}
pb2q
  • 58,613
  • 19
  • 146
  • 147
  • I'm not sure what you mean. Do you mean using variables which are object members? – pb2q Aug 20 '12 at 17:56
  • If you are referring to structs or C++ objects, it depends on whether they are allocated on the stack or the heap. – John Watts Aug 20 '12 at 17:57
  • 1
    When you intent to return a pointer to an integer (`int*`), you either need to have the member already allocated before calling the function, or allocate new memory using `malloc()`. You should **never return the pointer to a local variable as function output**. – behnam Aug 20 '12 at 17:57
  • @pb2q Scope and storage duration are different things, a variable can go out of scope but its storage could still exist. – ouah Aug 20 '12 at 17:58
  • @ouah I don't believe that I've confused the difference in my answer. If I have, suggest a re-wording? – pb2q Aug 20 '12 at 18:00
  • @pb2q `void foo(void) { int x, *bla = &x; bar(bla); }` In `bar` function `x` is also no longer in scope but `bar` has the right to modify `x`. I think scope has nothing to do with this issue. – ouah Aug 20 '12 at 18:10
0

For each function there will be an activation record, which will be created in stack once the execution of that function starts. Activation record holds all the local variables also. And this activation record will be freed once the function execution finishes.

So if we return an address of a local variable means, that will be freed memory of previous function`s activation record. Dereferencing that memrory is an undefined behaviour.

In the below case, function foo is returning the &x that means p will holds the address of func's local variable x. This is valid. But if function func tries to retrun p(address of x) which is not valid.

int* func
{
   int x;
   int *p;
   ...
   p = foo(&x);
   //using p is valid here
   ...
   return p; //This is invalid
}

int* foo(int *temp)
{
   int *x = temp;
   return x //This is valid
}

In the below case, funciton foo is returning address of its local variable x to function func. So p will holds address of foo's local variable. So deferencing p is invalid because foo functions execution has been completed and its activation record is freed.

int* func
{
   int x;
   int *p;
   ...
   p = foo(x);
   //using p is invalid here
   ...
   return p; //This is invalid
}

int* foo(int temp)
{
   int x = temp;
   return &x; //This is also invalid
}
rashok
  • 12,790
  • 16
  • 88
  • 100