From: Gordon Burditt
Newsgroups: comp.lang.c
Subject: Re: alloca()
Date: 25 Jan 1999 09:34:09 GMT
Message-ID: <16167775DFB6601E.39220BF5766349A7.B20FE25E4B4173B2@library-proxy.airnews.net>

>I'm curious to hear a little about a function called alloca().
>The (Solaris) man page I have here tells me that it allocates
>memory on the stack, which is then automatically freed when you
>return. Now, I'm well aware that alloca() is Not Standard And
>thus System Dependant and Beyond The Scope Of This Group,
>so please don't feel the need to reply just to tell me that. On
>the other hand, I'm interested to know how portable this is in
>practice, and what advantages and disadvantages it has w.r.t
>malloc() et al. I've seen it used a fair bit, and presumably the
>authors of the code must have had some reason for using it.

This function is one of the most horribly unportable abominations I have ever tried to implement. There are ways to try to implement it with malloc(), but if the memory is actually allocated on the stack, it causes lots of problems. You're pretty much stuck with needing to implement this in the compiler as a built-in.

You can write a function that knows about linkage conventions that adjusts the stack, but on one architecture (which didn't use a stack frame pointer), I ended up having to allocate something like 128 bytes extra on each call, due to possible register saving. That 128 byte figure was a guess as to what the worst case was, and I think it involved some (unreasonable) assumptions about the maximum number of arguments to functions that call alloca(). You did get those bytes back when the function exited. If it had been practical to modify the compiler-generated function exit sequences, life would have been much simpler.

What's the problem? Well, if you start allocating stuff on the stack when there's already stuff on the stack, you have alloca() allocating stuff in the middle of it, which really messes up argument passing, where stuff pushed on the stack is supposed to be contiguous. Horrible example:

    printf("%p %p %p %p %p\n", alloca(1), alloca(2), alloca(10), 
	alloca(8), alloca(20));

Now, where can you use alloca? I think this is reasonably safe:

You may use alloca() in the form of:

	pointer_variable = alloca(expression);
as an expression statement in the outermost block of a function.

You are asking for trouble if you use it anywhere that doesn't fit this description. You are likely to run into trouble if you use alloca() in any of these places, because there might be something on the stack at the point alloca() is called:

  1. Inside a loop.
  2. Inside any block that begins with local variables, except the outermost block of a function, especially if the allocated memory is used after exiting this block.
  3. Using any expression more complicated than a pointer variable on the left hand side of an assignment, including one element of an array of pointers.
  4. Where the return value of alloca() is used as a function argument.
  5. In any context where the value of the = operator is used, such as
    	if ((pointer_variable = 
    		alloca(sizeof(struct something))) == NULL) { .... }
    

And I expect that someone will call me on even THAT highly restrictive limitation not being conservative enough for the code generated by some compilers. Now, if it's done as a compiler builtin, you might manage to get around the problems.

Once I finally got that alloca() function figured out, it worked reasonably well - as I recall, the primary use for it was in a Bison parser. That 128 bytes wasted per invocation combined with a fixed stack size could be a nuisance. Why didn't I just use GCC? Because this was an attempt to port GCC, initially using cross-compilers, to a machine that turned out to barely have enough memory to compile GCC (1.35 or so) natively. When GCC 2 came out, it turned out to be enough of a memory pig that natively compiling itself was out of the question.

Gordon L. Burditt