Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is returning a stack allocated pointer variable in a function allowed in C?

I've read the followed post:

Is returning a heap-allocated pointer from function OK?

Which shows that a pointer pointing to a heap allocated variable is returned is alright. However, is the pointer technically a "stack allocated variable", which would then get deallocated upon returning of the function?

For example:

int* test(){
  int arr[5];
  int *ptr = arr;

  return ptr; //deallocated ptr?
}

int *test2(){
  int arr[5];

  return arr;
}

In test

Also, is it right to say arr is a pointer that points to some newly created int array arr, pointing at &arr[0]. If arr is not a pointer, why is it valid to return it satisfying the function return type?

Since both ptr and arr are supposedly stack allocated, why does the code only work in test() and not test2()? Does test() give an undefined behavior?

like image 244
oldselflearner1959 Avatar asked Apr 09 '19 12:04

oldselflearner1959


People also ask

Why shouldn't you return a pointer to something allocated on the stack?

Because it will cause undefined behavior in your program.

Are pointers allocated on the stack?

Pointer is allocated on the stack and the object it is pointing to is allocated on the heap. A pointer is an object.

Can a function return a stack?

At function return, the stack pointer is instead restored to the frame pointer, the value of the stack pointer just before the function was called. Each stack frame contains a stack pointer to the top of the frame immediately below.

Does a local variable allocate space on the stack?

Every time a function is called, the machine allocates some stack memory for it. When a new local variables is declared, more stack memory is allocated for that function to store the variable. Such allocations make the stack grow downwards.


2 Answers

They will both be undefined behaviour, if the returned value is accessed. So, none of them are "OK".

You're trying to return a pointer to a block-scoped variable which is of auto storage duration. So, once the scope ends, the lifetime of the variable comes to an end.

Quoting C11, chapter §6.2.4/P2, regarding the lifetime (emphasis mine)

The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address, and retains its last-stored value throughout its lifetime. If an object is referred to outside of its lifetime, the behavior is undefined [...]

Then, from P5,

An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration, [...]

and

For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way. [...]

So, in your case, the variable arr is having automatic storage and it's lifetime is limited to the function body. Once the address is returned to caller, attempt to access the memory at that address would be UB.

Oh, and there's no "stack" or "heap" in C standard, All we have is the lifetime of a variable.

like image 126
Sourav Ghosh Avatar answered Sep 21 '22 18:09

Sourav Ghosh


Both test and test2() are equivalent. They return an implementation-defined pointer that you must not dereference, or else UB ensues.

If you don't dereference the returned pointer, calling test() or test2() does not result in undefined behavior, but such a function is probably not very useful.

like image 28
PSkocik Avatar answered Sep 19 '22 18:09

PSkocik