cvariable-length-arraystack-framealloca

How does alloca() work on a memory level?


I'm trying to figure out how alloca() actually works on a memory level. From the linux man page:

The alloca() function allocates size bytes of space in the stack frame of the caller. This temporary space is automatically freed when the function that called alloca() returns to its caller.

Does this mean alloca() will forward the stack pointer by n bytes? Or where exactly is the newly created memory allocated?

And isn't this exactly the same as variable length arrays?

I know the implementation details are probably left to the OS and stuff. But I want to know how in general this is accomplished.


Solution

  • Yes, alloca is functionally equivalent to a local variable length array, i.e. this:

    int arr[n];
    

    and this:

    int *arr = alloca(n * sizeof(int));
    

    both allocate space for n elements of type int on the stack. The only differences between arr in each case is that 1) one is an actual array and the other is a pointer to the first element of an array, and 2) the array's lifetime ends with its enclosing scope, while the alloca memory's lifetime ends when the function returns. In both cases the array resides on the stack.

    As an example, given the following code:

    #include <stdio.h>
    #include <alloca.h>
    
    void foo(int n)
    {
        int a[n];
        int *b=alloca(n*sizeof(int));
        int c[n];
        printf("&a=%p, b=%p, &c=%p\n", (void *)a, (void *)b, (void *)c);
    }
    
    int main()
    {
        foo(5);
        return 0;
    }
    

    When I run this I get:

    &a=0x7ffc03af4370, b=0x7ffc03af4340, &c=0x7ffc03af4320
    

    Which shows that the the memory returned from alloca sits between the memory for the two VLAs.

    VLAs first appeared in the C standard in C99, but alloca was around well before that. The Linux man page states:

    CONFORMING TO

    This function is not in POSIX.1-2001.

    There is evidence that the alloca() function appeared in 32V, PWB, PWB.2, 3BSD, and 4BSD. There is a man page for it in 4.3BSD. Linux uses the GNU version.

    BSD 3 dates back to the late 70's, so alloca was an early nonstandardized attempt at VLAs before they were added to the standard.

    Today, unless you're using a compiler that doesn't support VLAs (such as MSVC), there's really no reason to use this function since VLAs are now a standardized way to get the same functionality.