A particular problem is that if alloca() is used as a function
OTOH, how often have you felt the need to use alloca this way?
No, but I have had occasion to try to use alloca() where it was passed as
ONE argument to a function, neither first nor last, and I ended up tearing
my hair out trying to figure out why it didn't work. The problem was
that the data got allocated in THE MIDDLE of the block of arguments.
A later version did the right thing as long as it didn't run out of registers,
which is why there are so many parameters in the example. However, trying to
guess how many registers were in use required anticipating how the compiler
would do things, and depended in many ways on optimization settings and
even a few things you wouldn't normally expect to be optimization (like
the writable-strings option).
This is by no means the most complicated situation that I would expect to break.
It gets even messier if the value passed to alloca() is not constant but requires
the use of alloca() to calculate it.
Although I'm far from being an alloca advocate, I find this example
highly artificial and irrelevant for the typical use of alloca. Even if
the sizes are not constant, as in your trivial example.
You're right, the example is artificial. It's supposed to be simple to
make it easy to check if the generated code is broken.
If I'm going to use alloca() I want to know whether it will work
or not. The above example is certainly not typical but there seems
to be no way of knowing when you cross the line, and further, nobody
seems to know or care. (I also expect unsigned arithmetic to work
in more than just the "typical" cases). I note that one poster notes
that it's still broken with VLAs. I could live with that if I could
be reasonably sure that the implementations are all that good. And
especially if this limitation was actually documented.
I think there are still compilers out there that claim to implement
alloca() without treating it as a compiler builtin, or at least
generating code specially when it's being used. I don't believe
that's possible without seriously slowing down the code by assuming
that ALL functions are alloca-like.
At one time I spent a lot of time trying to port alloca() to another
architecture where it appeared to work if you used it in the context:
<variable> = alloca( <integer expression not involving use of alloca()>);
in the outer block of a function, but otherwise I could manage
without trying very hard manage to break it, in both the architecture
I was porting it to and all the architectures where it was already
implemented. The answers I got were always that I was abusing it
in some way and I shouldn't do that. That's nice, how about
documenting where I CAN use it? Or maybe an actual error message
if it can't manage to do the right thing, rather than silence until
it bombs in strange ways at runtime? Oh, yes, the restrictions
varied a lot from architecture to architecture even in the same
compiler version. One of them even managed to break:
if ((ptr = alloca(sizeof(struct foo))) != NULL) {
char name[100];
...
}
and actually documented that! The fix was:
ptr = alloca(sizeof(struct foo));
if (ptr != NULL) {
char name[100];
...
}
Gordon L. Burditt