0

Is the following function safe, to return a pointer to a local variable?

int * foo(void)
{
    int a = 6;
    int *p = &a;
    return p;
}

if not, at what conditions? if yes, how the safety is guaranteed by the compiler?

Test cases tried:

int * foo(void)
{
    int a = 6;
    int *p = &a;
    return p;
}

int * bar(void)
{
    int b = 7;
    int *p = &b;
    return p;
}

int main()
{
    int a = *foo();
    int b = *bar();
    printf("%d, %d, %d\n", 1, 2, 3); //to mess up stack
    printf("%d, %d\n", a, b);
    return 0;
}

it will successfully print "6, 7". However with -O2 it prints "0, 0"

Kevin Y.
  • 139
  • 1
  • 6

3 Answers3

3

The result of doing that will be undefined behavior and it is definitely not safe.

a is a variable local to a function (ie: automatic variable) hence it is stored in the stack. When the function returns the stack frame is moved up (or down) and the memory left there will potentially be overwritten by the next called function so te pointer would be pointing to the same direction in memory but can be any random byte.

Paulo Bu
  • 29,294
  • 6
  • 74
  • 73
1

This function is not safe, ever. It may accidentally happen to do what you expect some of the time, but that's all.

Slightly less terse: Returning a pointer to a local variable always provokes undefined behavior. Undefined behavior includes the possibility that nothing bad will happen this time, and the usual stack-based implementation of C allows you to get away with dereferencing pointers into memory immediately "above" the top of the stack, most of the time. Your main dereferences those pointers immediately after the function returns, which makes it more likely to "work" (in particular, your "to mess up the stack" printf isn't affecting anything because the invalid pointers are dead already at that point). However, an implementation that arranged for int a = *foo() to segfault would be conforming.

Fun fact: the word "stack" does not appear in the text of C99. All implementations are required to support recursive function calls, and the usual way to do that is with a stack, but a stack is not the only way to do it. Consider, for instance, Cheney on the M.T.A. in which the underlying C stack is repurposed as a garbage collector nursery, and all continuations are explicit -- a C implementation would be just as allowed to do that as a Scheme implementation.

zwol
  • 135,547
  • 38
  • 252
  • 361
1

Short answer, it is never safe, because sooner or later the memory allocated to that variable will be reused.

It works for your examples, because they are simple, and not much else has happened on the stack between returning the pointer and accessing the memory to which it points.

It is only safe if the memory to which you return a pointer is explicitly allocated with malloc or similar.

this link explains the point better and in more detail: http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/Mips/stack.html

Angst
  • 304
  • 1
  • 9
  • 14