C - Avoiding warning "address of stack memory associated with local variable returned"

Viewed 1320

I've written the following simple program that sums up the numbers from 0 to 9:

#include <stdio.h>
#include <stdlib.h>

int* allocArray() {
    int arr[10];
    return arr;
}

int main(void){
    int* p;
    int summe = 0;
    p = allocArray();
    for(int i = 0; i != 10; ++i) {
        p[i] = i;
    }
    for(int i = 0; i != 10; ++i) {
        summe += p[i];
    }
    printf("Sum = %d\n", summe);
}

The code compiles and delivers the expected result "45". However I get the following warning: 'address of stack memory associated with local variable 'arr' returned'. What am I doing wrong?

2 Answers

This is undefined behaviour, plain and simple. The only reason it "works" is because with this particular compiler the stack hasn't been trashed yet, but it is living on borrowed time.

The lifetime of arr ends immediately when the function call is complete. After that point any pointers to arr are invalidated and cannot be used.1

Your compiler uses stack memory to store local variables, and the warning indicates that you're returning an address to a now-invalidated stack variable.

The only way to work around this is to allocate memory dynamically and return that:

int* allocArray() {
    int* arr = calloc(10, sizeof(int));

    return arr;
}

Where you're now responsible for releasing that memory later.

You can also use static to extend the lifetime of arr:

int* allocArray() {
    static int arr[10];

    return arr;
}

Though this is not without consequences, either, as now arr is shared, not unique to each function call.


1 Like a lot of things in C there's significant overlap between what you "cannot do" because they lead to undefined behaviour and/or crashes and what you "can do" because it's permitted by the syntax and compiler. It's often your responsibility to know the consequences of any code you write, implied or otherwise.

To keep it in your code:

int arr[10];

will allocate the memory on the stack. As soon as you are leaving the function, the content of that array will be overwritten pretty soon. You want to allocate this on the heap.

You would need to use

int* arr = malloc(sizeof(int)*10);

and in the main function, after you've used it (at the end of main), call

delete[] arr;

Nevertheless, this code could be better if the ownership of the array would be properly handled. You want to make yourself familiar with C++ containers and shared/unique pointers.

Related