From what I know, local variables (not declared using the static
keyword) within functions only exist for as long as the function is on the stack frame and when control returns to the caller all local variables are destroyed. This would explain why it is not possible to return a locally defined array from a function. Trying to dereference such an array returned would give us garbage values at best or a segfault at worst. Shouldn't this also be true for structures? That is, if we are returning a structure from a function, shouldn't trying to access its members also give us garbage values or a segfault?
I have the following two files for demonstrating. The first one is for arrays:
/* return_local_vs_malloc_array.c */
#include <stdio.h>
#include <stdlib.h>
#define LEN 10
#define VAL 100
int *return_local() {
int arr[LEN] = {VAL};
return arr;
}
int *return_mallocated() {
int *arr = (int *)malloc(sizeof(int)*LEN);
for (int i = 0; i < LEN; i++)
arr[i] = VAL;
return arr;
}
void display(int *arr) {
for (int i = 0; i < LEN; i++) {
printf("%d ", arr[i]);
}
putchar('\n');
}
int main(void) {
int *x = return_local();
fputs("local: ", stdout); display(x);
int *y = return_mallocated();
fputs("malloc: ", stdout); display(y);
free(y);
return 0;
}
and the other one is for structs:
/* return_local_vs_malloc_struct.c */
#include <stdio.h>
#include <stdlib.h>
struct foobar {
int foo;
int bar;
};
struct foobar return_local(int foo, int bar) {
struct foobar f;
f.foo = foo;
f.bar = bar;
return f;
}
struct foobar *return_mallocated(int foo, int bar) {
struct foobar *f = (struct foobar *)malloc(sizeof(struct foobar));
f->foo = foo;
f->bar = bar;
return f;
}
int main(void) {
struct foobar x = return_local(10, 20);
printf("local: x = {foo: %d, bar: %d}\n", x.foo, x.bar);
struct foobar *y = return_mallocated(10, 20);
printf("malloc: y = {foo: %d, bar: %d}\n", y->foo, y->bar);
free(y);
return 0;
}
When I run this I get:
$ tcc -run ./return_local_vs_malloc_array.c
local: x = -1519296757 32767 0 0 -849137592 32767 -849137536 7 -849137608 32767
malloc: y = 100 100 100 100 100 100 100 100 100 100
~/
$ tcc -run ./return_local_vs_malloc_struct.c
local: x = {foo: 10, bar: 20}
malloc: y = {foo: 10, bar: 20}
As you can see, the locally allocated structure persists even when control has returned from the function in which it was declared. From what I know, this is not supposed to happen and the only way one can make a local variable persist beyond the lifetime of the called function is by using the static
qualifier. But maybe I am wrong?