2

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?

Monika
  • 301
  • 3
  • 12
  • 2
    Does this answer your question? [Returning an array using C](https://stackoverflow.com/questions/11656532/returning-an-array-using-c) – Stephen Newell Jan 22 '21 at 15:49
  • 1
    Protip: When you get a weird error message, copy and paste the exact text of the error message into the google search box, [like this](https://www.google.com/search?q=address+of+stack+memory+associated+with+local+variable+returned). Chances are, someone else has been puzzled by the same error, and has asked abut it, and gotten answers. – Steve Summit Jan 22 '21 at 15:55
  • Note though that it's a bewilderingly long scroll down that page before [someone finally mentions](https://stackoverflow.com/a/28970797/2757035) the option of wrapping the array in a `struct`, which is a perfectly good way to do this while avoiding dynamic allocation (and how C++ implements its properly value-semantic `std::array`). – underscore_d Jan 22 '21 at 15:55
  • Same error message: *[Using C-string gives Warning: "Address of stack memory associated with local variable returned"](https://stackoverflow.com/questions/18041100/)* – Peter Mortensen Oct 22 '22 at 05:05

2 Answers2

5

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.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • Ooops, almost identical answer :) – David Ranieri Jan 22 '21 at 15:54
  • It is not undefined behavior - it is a kind of "use after free". – Zuppa Jan 22 '21 at 19:07
  • @Zuppa, this is literally undefined behavior. The standard states that `the lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it... If an object is referred to outside of its lifetime, the behavior is undefined`. – embedded_guy Jan 22 '21 at 21:23
  • @embedded_guy point taken. imho in this case the wording 'undefined behavior' is still a bit weak :) – Zuppa Jan 30 '21 at 07:46
0

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.

Zuppa
  • 467
  • 5
  • 16