0

If I have the following:

int *test()
{
    int d = 10;
    int a[d];

    a[0] = 10;
    a[1] = 20;

    printf("%p\n", a);

    return a;

}

int main(void)
{
    int *a = test();

    printf("%p %d\n", a, a[0]);

    return 0;
} 

when I return a from test to main the memory allocated for a inside test is not destroyed. But why? Isn't a an automatic storage variable that die when the block function exit? In fact when I compile the code the compiler warn me with:

function returns address of local variable [-Wreturn-local-addr]

The same thing happen if I use a static array.

xdevel2000
  • 20,780
  • 41
  • 129
  • 196
  • 1
    The accepted answer to the question I linked says “Undefined Behavior means anything can happen, including it'll do as you expect. Your stack variables weren't overwritten in this case”. This is the answer to your question as well. – Pascal Cuoq Mar 18 '14 at 09:57
  • 1
    I'd really like to link to http://stackoverflow.com/a/6445794/15727 even if that question is about C++. – Thomas Padron-McCarthy Mar 18 '14 at 10:10
  • @PascalCuoq, Dangling pointer? I don't think this is the case. The address is assigned to another variable so where is the dangling pointer? Maybe when the function exit is the a itself that is removed from the stack. – xdevel2000 Mar 18 '14 at 10:12
  • @ThomasPadron-McCarthy I almost picked that one as duplicate, but I don't want to reinforce the meme that C and C++ are the same language. – Pascal Cuoq Mar 18 '14 at 10:19
  • 1
    @xdevel2000 Your program is a textbook illustration of dangling pointers. Specifically, variable `a` when the call to `printf` is reached is a textbook example of a dangling pointer. See the first example in http://en.wikipedia.org/wiki/Dangling_pointer . This is what your program does. Or compare to the third example on that page. – Pascal Cuoq Mar 18 '14 at 10:21
  • Please read the link posted by Thomas, it answers the question. – Lundin Mar 18 '14 at 10:35

3 Answers3

3

The requirement is not for the memory to be "destroyed" (whatever it could mean - filling with zeros?) the standard says only that such code as yours triggers undefined behaviour - and undefined behaviour may mean anything, including the situation in which the memory for some time has the same content. But still it is undefined behaviour and your code is erroneous.

Wojtek Surowka
  • 20,535
  • 4
  • 44
  • 51
1

There is no requirement in the C standard to "destroy" the data stored in a variable that goes out of scope.

It isn't safe to access a after it has gone out of scope. The memory is free to use for other purposes. What happens if you access the memory is unspecified. It may return the value you put there, it may return some other (junk) value, it may cause a program crash or it may blow up the island of Manhattan.

The last option is very unlikely though, I haven't come across any C compiler that generates code that does that.

Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82
1

a is a local variable. "Local" as in function-local. a doesn't exist any more once test() returns. Thus you return a pointer to an object that doesn't exist any more, and the compiler rightly complains.

You can either pass an array as parameter to test() and fill that array within test(), or you can actively allocate memory on the heap with malloc() within test() and return a pointer to that. Note that the caller then has to free() said memory again to prevent memory leaking.

Christian Aichinger
  • 6,989
  • 4
  • 40
  • 60
  • 1
    `a` is an **automatic variable** as defined in the C standard. The question gets this right. Why confuse the issue with fuzzy vocabulary? – Pascal Cuoq Mar 18 '14 at 10:02
  • Exactly the kind of "fuzzy" vocabulary the compiler uses... ``function returns address of local variable``. Relying on undefined behavior of C compilers is bad practice and should be avoided. It just asks for subtle breakage if your assumption is ever violated in future compilers. – Christian Aichinger Mar 18 '14 at 10:10
  • “Relying on undefined behavior of C compilers is bad practice” I am not disputing that part of your answer. In fact, I even wrote a blog post in which I argue that you should not assume that `a` contains an `int` after `{ int a;` even if you know that your platform has no trap representations for `int`: http://blog.frama-c.com/index.php?post/2013/03/13/indeterminate-undefined – Pascal Cuoq Mar 18 '14 at 10:14