alloca

H

Harald van Dijk

It is not mentioned because it does not exist in standard C, and
programs calling it are no longer portable.

They never were portable in the sense that you use it.
It is not even
implementable in a portable manner.

It may require compiler help, but assuming compiler help is available,
it's implementable on every system. And if compiler help is not available,
then discussing implementation modifications is fairly meaningless.
If I am right about this, you can't
even give topical code for it on this newsgroup.

Of course, because any code he would give, even if in direct response to
your request in this newsgroup, would be discarded as nontopical.

You could've just stopped at "It is not mentioned because it does not
exist in standard C".
 
E

Eric Sosman

Bartc said:
Eric Sosman said:
o Even on systems where alloca() is available, it may fail
catastrophically in some contexts, for example

ptr = fgets(alloca(SIZE), SIZE, stdin);

Why should that failure be any more likely than:

void fn()
{char buffer[SIZE];
...
ptr = fgets(buffer, SIZE, stdin);

If the implementation uses a stack for alloca() and for local variables,
then it seems stack overflow is equally likely.

The "embedded" alloca() carries a further danger: Machines
that pass function arguments on the same stack from which alloca()
obtains memory are likely to botch the argument list. Instead of

[ FILE* ]
[ size_t ]
[ char* ]

.... the function may receive a stack that looks like

[ FILE* ]
[ size_t ]
[ b ]
[ u ]
[ f ]
[ f ]
[ e ]
[ r ]
[ char* ]

.... with unwelcome consequences. In order to avoid this,
the compiler needs to special-case the handling of function
arguments involving alloca(), rewriting to something like

char *_temp = alloca(SIZE);
ptr = fgets(_temp, SIZE, stdin);

Jacob, does your compiler do this transformation, or
something similar?
 
B

Bartc

Eric Sosman said:
Bartc said:
Eric Sosman said:
o Even on systems where alloca() is available, it may fail
catastrophically in some contexts, for example

ptr = fgets(alloca(SIZE), SIZE, stdin);

Why should that failure be any more likely than:

void fn()
{char buffer[SIZE];
...
ptr = fgets(buffer, SIZE, stdin);
The "embedded" alloca() carries a further danger: Machines
that pass function arguments on the same stack from which alloca()
obtains memory are likely to botch the argument list. Instead of

[ FILE* ]
[ size_t ]
[ char* ]

... the function may receive a stack that looks like

[ FILE* ]
[ size_t ]
[ b ]
[ u ]
[ f ]
[ f ]
[ e ]
[ r ]
[ char* ]

Good answer. I was thinking of the equal likelihood of running out of stack
space.
In order to avoid this,
the compiler needs to special-case the handling of function
arguments involving alloca(), rewriting to something like

char *_temp = alloca(SIZE);
ptr = fgets(_temp, SIZE, stdin);

I did a quick test [on lccwin32], function calls as arguments tend to be
dealt with separately from the actual parameter pushing, don't think
alloca() had special treatment.
 
R

Richard Tobin

Walter Roberson said:
It is not possible to write a general alloca() that exists
outside of the intimate details of the ABI in use. It therefore
must not be thought of as belonging to C: it belongs to the
system extensions that C compiler provides for that operating
environment. That makes it topical in the newsgroups that discuss
those operating environment specifics, not topical in comp.lang.c .

And yet people have written code that uses alloca() without the
slightest regard for the details of the ABI in use. They have
used it in portable code: not portable to every C implementation,
but portability is not absolute. If one wants to talk about alloca()
in general, then this is the place to do it.

-- Richard
 
R

Richard Tobin

Malcolm McLean said:
Oddly enough alloca is on topic in comp.std.c, because that's the place to
discuss proposed changes to the C standard.

Just because something isn't in the C standard doesn't mean that its
only interest to C programmers is as a proposed addition. alloca() is
used in existing C implementations, in code not intended for a single
system. Discussions of such subjects as how portable it is, and when
it's a good idea to use it, belong here.

-- Richard
 
A

Andrey Tarasevich

jacob said:
This function is not mentioned very often in this newsgroup but it
is a VERY useful function, implemented in most compilers.

I think it is useful to point to it since many people that read this
newsgroup are newcomers, and they could benefit by using it.
...

Memory allocated by 'alloca' function obeys rather artificial non-C-ish
lifetime rules, which might easily lead to rather nasty surprises when
used without caution (did anyone mention newcomers?). In C99 language
VLAs provide support for run-time sized automatic memory, essentially
eliminating the need for 'alloca'.
 
G

Gordon Burditt

This function is not mentioned very often in this newsgroup but it
is a VERY useful function, implemented in most compilers.

And, unfortunately, *MIS*-implemented in many.
I think it is useful to point to it since many people that read this
newsgroup are newcomers, and they could benefit by using it.

This function is an allocation function, i.e. it is similar in
functionality to the malloc() function, but it has the advantage of
allocating from the stack instead of allocating from the heap.

Disadvantages:

- In all the implementations I have seen, it does NOT make any attempt
to detect stack overflow and return NULL on error. This is a
serious problem, the gets() of memory allocation.
- There is no way to free memory except by exiting the function, which
means that alloca() called within a loop can accumulate a lot of
no-longer-used storage. Well, that's just a situation where malloc()
should be used rather than alloca().
- It is not a standard C function.
- alloca(), when implemented not as a wrapper for malloc() but actually
allocating storage on the stack, cannot work reliably if the compiler
does not know that alloca() is being called, otherwise, there is a
tendancy for it to allocate blocks of memory in the middle of function
parameter lists, causing garbage to be passed to functions.
This means that if you take the address of alloca(), put it in a function
pointer, and then call it indirectly, unless the compiler can figure
out that it might be a call to alloca(), it is likely to malfunction.
(gcc on FreeBSD makes taking the address of alloca() fail, probably
the best way to avoid this.)


Test your version of alloca():

- Put the program below into a file.
- Add whatever header is needed to declare alloca().
- Compile it and run it.
- Verify that the first line of output contains "1 = 1" and the
third line contains "2 = 2". If not, something failed.
- When reporting results, include your processor, OS, version, compiler,
and it's version, and what compiler flags you used.
- Try and see if there are any differences with different optimization flags.

Incidentally, on i386, FreeBSD 6.2 with gcc 3.4.6, it seems to use
32 bytes each for alloca(3). No optimization, -O, -O2, and -O3 all
produce correct results.

It's intended that in this test program, the number of alloca()
calls exceeds the number of registers the compiler can use to pass
function parameters. If that's not the case for your platform,
edit accordingly.

#include <stdlib.h>

int main(int argc, char **argv)
{
printf("1 = %d\n%p %p %p %p %p %p %p %p %p %p %p\n2 = %d\n",
1,
alloca(3),
alloca(3),
alloca(3),
alloca(3),
alloca(3),
alloca(3),
alloca(3),
alloca(3),
alloca(3),
alloca(3),
alloca(3),
2);
exit(EXIT_SUCCESS);
}
 
R

Richard Tobin

CBFalconer said:
It is not even implementable in a portable manner.

What does this mean? Is addition implementable in a portable manner?
Is switch? Is setjmp()?

Do you just mean it's hard to implement efficiently on some systems?

It's certainly *possible* to implement it on all systems: if all else
fails, use malloc(), and make the return code from functions that use
it do any necessary free()ing. You'd also need to make longjmp() more
complicated.

-- Richard
 
A

Andrey Tarasevich

Walter said:
...
It is not possible to write a general alloca() that exists
outside of the intimate details of the ABI in use. It therefore
must not be thought of as belonging to C: it belongs to the
system extensions that C compiler provides for that operating
environment.

Sorry, but none of the standard library functions are required to be
writable in pure C (as opposed to relying on "the intimate details of
the ABI in use"). Something like this is not supposed to be used as a
criterion for library inclusion (or non-inclusion).
 
A

Andrey Tarasevich

Eric said:
...
That's odd: The Rationale says "Such a function is not
efficiently implementable in a variety of environments, so
it was not adopted in the Standard." What do you know that
the couple hundred contributors to the Standard didn't?
...

Today the above "rationale" is obviously incorrect. I'm not saying that
people who came up with this rationale were wrong. It is quite possible
that they were right at the time when they came up with it. However,
today the Variable Length Arrays (VLAs) are part of the C99 standard.
And the complexities of implementing VLAs are exactly the same (or even
more severe) than the difficulties that arise in implementation of
'alloca' function. Yet VLAs have made it into the standard.

Actually the real reason why we don't need to care about 'alloca'
anymore is the simple fact that its benefits are already provided by a
more C-like feature - VLAs.
 
A

Andrey Tarasevich

Eric said:
... the function may receive a stack that looks like

[ FILE* ]
[ size_t ]
[ b ]
[ u ]
[ f ]
[ f ]
[ e ]
[ r ]
[ char* ]

... with unwelcome consequences. In order to avoid this,
the compiler needs to special-case the handling of function
arguments involving alloca(), rewriting to something like

char *_temp = alloca(SIZE);
ptr = fgets(_temp, SIZE, stdin);
...

This is, of course, a fake argument. A compiler that provides the
'alloca' as a library extension has to make sure that the argument
passing mechanism works correctly. How it does that it its own headache.

For example, a compiler can decide to _always_ perform the calls to
argument-forming functions before starting to form the next stack frame.
(no need to single out the 'alloca').
 
R

Richard Tobin

Gordon Burditt said:
This means that if you take the address of alloca(), put it in a function
pointer, and then call it indirectly, unless the compiler can figure
out that it might be a call to alloca(), it is likely to malfunction.

No-one in their right mind would do that :) Incidentally, does the
standard prohibit doing it with setjmp()?

On MacOS (see below), if you succeed in fooling gcc into treating
alloca as a normal function you get an undefined symbol in the linker.
There is no real function called "alloca".
Test your version of alloca():

Unsurprisingly works fine with gcc 4.0.1 on MacOS X Leopard on PPC,
with all the optimisation levels. Gcc recognises alloca().
Incidentally, on i386, FreeBSD 6.2 with gcc 3.4.6, it seems to use
32 bytes each for alloca(3).

Same on MacOS. It's odd, since it isn't always 32-byte aligned.
It's intended that in this test program, the number of alloca()
calls exceeds the number of registers the compiler can use to pass
function parameters. If that's not the case for your platform,
edit accordingly.

From the generated code it appears that 8 arguments are passed in
registers, but I'm not 100% sure.

-- Richard
 
R

Richard Tobin

Andrey Tarasevich said:
And the complexities of implementing VLAs are exactly the same (or even
more severe) than the difficulties that arise in implementation of
'alloca' function.

Is this quite true? Consider alloca() in a loop.

-- Richard
 
G

Gordon Burditt

Today the above "rationale" is obviously incorrect. I'm not saying that
people who came up with this rationale were wrong. It is quite possible
that they were right at the time when they came up with it. However,

Some processors and linkage conventions made implementing alloca()
difficult. One I remember doing involved copying about 100 bytes
of stack frame (saved registers) and using that much stack, even
for alloca(1).
today the Variable Length Arrays (VLAs) are part of the C99 standard.
And the complexities of implementing VLAs are exactly the same (or even
more severe) than the difficulties that arise in implementation of
'alloca' function. Yet VLAs have made it into the standard.

I disagree: alloca() presents problems that VLAs don't. You can't
declare a VLA in the middle of a function argument list, but you
*can* call alloca() in the middle of a function argument list. This
risks having alloca() take its memory in the middle of a function
argument list, unless the compiler is careful to avoid generating
code that way. You can't hide a VLA declaration by putting the
address of alloca() in a function pointer and using the pointer to
call alloca().
 
C

CBFalconer

Richard said:
And yet people have written code that uses alloca() without the
slightest regard for the details of the ABI in use. They have
used it in portable code: not portable to every C implementation,
but portability is not absolute. If one wants to talk about
alloca() in general, then this is the place to do it.

Portability is much more 'absolute' than you seem to think. The
point about the C standard is that it guarantees that code meeting
its requirements will run correctly on any system meeting those
requirements. alloca is not included in those requirements.
 
C

CBFalconer

Harald said:
CBFalconer wrote:
.... snip about alloca ...


Of course, because any code he would give, even if in direct
response to your request in this newsgroup, would be discarded
as nontopical.

You could've just stopped at "It is not mentioned because it
does not exist in standard C".

No, code you can write down, that is portable, is topical here.
However you can't do that for alloca. For example, you can code
'between' to decide if a <= b <= c, by:

int between(int a, int b, int c) {
if ((a <= b) && (b <= c)) return 1;
return 0;
}
 
J

Jack Klein

This function is not mentioned very often in this newsgroup but it
is a VERY useful function, implemented in most compilers.

After all these years, I have finally lost patience with your
megalomania. Obviously, you and only you are qualified and entitled
to dictate the topic of this group. NOT.

*plonk*

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
A

Andrey Tarasevich

Richard said:
...

Is this quite true? Consider alloca() in a loop.
...

Huh? I don't understand what your are trying to argue by providing an argument
that supports (and illustrates) _my_ point of view...

Exactly: consider alloca() in a loop. As I said before, 'alloca' does not care
about C scoping/lifetime rules, while VLAs must strictly observe there rules,
which make VLAs _more_ complex to implement.

Of course, if just consider the common parts of VLAs and 'alloca' (namely, the
allocation itself), the difficulties in implementing them, once again, are
exactly the same. VLAs are nothing else than a cultured version of 'alloca'.
 
B

Bertrand Mollinier Toublet

jacob said:
What makes this function interesting is that
o It is very efficient. Since it allocates from the stack,
a few assembler instructions are needed, much quicker
than most "malloc" implementations.

Well, as it turns out, I have now 7 years of C programming experience
(including on some fairly small systems with not much oompf), and I have
yet to run into a case where my (standard C) programming is creating
efficiency issues.
o The storage is freed automatically when the function where
it is called exits. No need to call free().
I don't understand how the good practice of disposing at the relevant
location of any resources brought into use could be seen as bad
programming. This general concept of course includes free-ing malloc'd
memory.


In my world, therefore, nothing is left to make this function interesting...

Ah, but the caveats are still there, though...
 
A

Andrey Tarasevich

Gordon said:
...

I disagree: alloca() presents problems that VLAs don't. You can't
declare a VLA in the middle of a function argument list, but you
*can* call alloca() in the middle of a function argument list. This
risks having alloca() take its memory in the middle of a function
argument list, unless the compiler is careful to avoid generating
code that way.

You are trying to present invented trivial problems as something critical. It is
the implementation that is supposed to care about the correctness of the code in
this case. How it does that is entirely not my business. It might evaluate all
arguments before starting to form the argument list. It might use some kind of
"compiler magic".

BTW, I read the messages here and some of them seem to demonstrate that weird
and distorted perception of the standard library (maybe in its extended form) as
something completely independent from the core language implementation. People
seem to believe somehow that the compiler might not have any idea about the
difficulties 'alloca' might present. I understand that this is probably rooted
in that archaic view of C language and its libraries specific to the early age
of UNIX-like systems. This is actually a bigger distortion of the concept of
standard C than the original poster's suggestion of using 'alloca'.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top