gcc and alloca

O

Old Wolf

OTOH, alloca is *far* more portable than VLAs... Fortunately, it can
be replaced by malloc and friends in most cases (the only excuse for using
alloca is when malloc and friends render the code too slow for its
intended purpose on its intended platform).

Or if there is no free store (ie. malloc always returns 0)
 
G

Gordon Burditt

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
 
R

Richard Tobin

There is nothing preventing you from doing the cleanup *before* calling
longjmp.

That's why I said "complicated" rather than "impossible".
And if the code is carefully designed, the cleanup is always
trivial (just take care that each involved pointer is either null or
allocated and call free() on all of them).

What if the longjmp() is from a function in a library you don't
control? (In that case it probably *is* impossible.) Even in the
more common case that the function calling longjmp() is your own, you
would probably need to keep a list of the relevant pointers.

-- Richard
 
P

Peter Ammon

Gordon said:
I believe that alloca() is impossible to implement correctly without
making it a built-in and very difficult to either make work
unrestricted or describe the limits of where you can use it and
where you cannot even if it is a builtin. Early (e.g. a decade or
two ago) versions of GCC that had it as a builtin got it wrong.
Current versions may or may not handle it properly.

Well, 'tain't entirely so. Go & ogle "BeOS alloca" for the mostly
portable alloca() implemented in standard C; it's the first link.
A particular problem is that if alloca() is used as a function
argument, arranging NOT to have the space end up somewhere in
the middle of the arguments of the called function.

Look at the generated code for this:

foo(
alloca(10),
alloca(20),
alloca(30),
alloca(40),
alloca(50),
alloca(60),
alloca(70),
alloca(80),
alloca(90),
alloca(100),
alloca(110),
alloca(120),
alloca(130),
alloca(140),
alloca(150),
alloca(160),
alloca(170),
alloca(180),
alloca(190)
);

and see if the arguments passed are 19 pointers and no part of an
uninitialized memory area. If it calls alloca(), pushes the result,
and repeats 19 times, it's going to get it wrong.

Gordon L. Burditt

Not sure what you mean by "pushes the result" and whatnot, but for me
gcc just increments the stack pointer a bunch of times, stores pointers
to the chunks of space it gets in registers, and then jumps off to
foo(). Looks right to me.

-Peter
 
D

Dan Pop

In said:
That only works if you're calling longjmp directly from that function,
and not from something that it calls.

If there are intermediate functions that need cleanup, longjmp is not an
option in the first place. Think about functions having open streams, to
remain in the realm of standard C (but real life applications can also
allocate other kinds of resources that require proper deallocation).

Dan
 
D

Dan Pop

In said:
(e-mail address removed) (Dan Pop) wrote:.

Or if there is no free store (ie. malloc always returns 0)

Expect an alloca() call to either fail or crash your program in this
scenario.

Dan
 
D

Dan Pop

In said:
What if the longjmp() is from a function in a library you don't
control? (In that case it probably *is* impossible.)

In that case it is the library's implementor job to do the right thing,
whatever that is, including not using longjmp.

Dan
 
M

Mark McIntyre

Some people here have started saying that "alloca"
is off topic, and they used the argument that the gcc
compiler doesn't recognize it.

No, they didn't. You eithe misunderstand or distort the truth.

The argument was that when invoked in ISO compatible mode, gcc didn't
recognise alloca(), which was to be expected since its not ISO, and since
ISO is the topic here, ergo its offtopic.
I am not related in anyway to the developers of the gcc
compiler but seeing the facts of their implementation
I can't imagine that they would take the effort of making
a BUILT-IN (__builtin) function if they did not want
people to use it.

I'm confused. Why do you think that the existence of the function, and
presumably the intention of the developers that someone could use it, has
/anything/ at all to do with topicality here? My compiler for PalmOS has
various functions to manipilate the SD card builtin. MSVC has a stack of
windows kernel functions "builtin". Are they topical here?
The gcc compiler in its *default* setting supports alloca
even better than lcc-win32 since they made it a builtin.

Whoopy do.
 
J

jacob navia

Mark McIntyre said:
No, they didn't. You eithe misunderstand or distort the truth.

In another thread in this group ("Target audience" where you also
participated) Mr Dave Vandervies wrote:

<QUOTE>
jacob navia said:
All linux compilers and windows compilers supply alloca.

Really? So is it gcc or uname that's lying to me here?
--------
dave@hct-cvs:~/clc (0) $ cat foo.c
/*There's a man page that claims alloca is declared in stdlib.h, so this
is a best-guess about how to get it.
*/
#include <stdlib.h>

int main(void)
{
alloca();

return 0;
}
dave@hct-cvs:~/clc (0) $ gcc -W -Wall -ansi -pedantic -O foo.c
foo.c: In function `main':
foo.c:8: warning: implicit declaration of function `alloca'
/tmp/ccn8UpcR.o: In function `main':
/tmp/ccn8UpcR.o(.text+0x4): undefined reference to `alloca'
collect2: ld returned 1 exit status
dave@hct-cvs:~/clc (1) $ gcc --version
egcs-2.91.66
dave@hct-cvs:~/clc (0) $ uname -a
Linux hct-cvs 2.2.16 #9 Thu Mar 13 16:55:23 EST 2003 i586 unknown
dave@hct-cvs:~/clc (0) $
--------

gcc claims it doesn't have a declaration for alloca, the linker claims
it can't find it in the library, and uname claims that I'm running Linux
(which you say necessarily supports it).

I'm inclined to think that it's you, and not the programs I'm running,
that's mistaken.


dave

--
Dave Vandervies (e-mail address removed)
There is no possible way that CHAR_MIN can be 255, and certainly no way
that CHAR_MIN can exceed 255.
--Ben Pfaff in comp.lang.c

<end quote>
 
K

Keith Thompson

jacob navia said:
In another thread in this group ("Target audience" where you also
participated) Mr Dave Vandervies wrote:

<QUOTE>


Really? So is it gcc or uname that's lying to me here?
--------
dave@hct-cvs:~/clc (0) $ cat foo.c
/*There's a man page that claims alloca is declared in stdlib.h, so this
is a best-guess about how to get it.
*/
[snip]

Yeah, Dave made a mistake. alloca(), on all the systems I've checked,
is declared in <alloca.h>, not in <stdlib.h>.

In any case, Dave said (incorrectly) that gcc doesn't recognize
alloca(); he didn't claim that alloca() is off topic *because* gcc
doesn't recognize it, nor did anyone else.
 
D

Dan Pop

In said:
Yeah, Dave made a mistake. alloca(), on all the systems I've checked,
is declared in <alloca.h>, not in <stdlib.h>.

Check the glibc <stdlib.h>:

#if defined __USE_GNU || defined __USE_BSD || defined __USE_MISC
# include <alloca.h>
#endif /* Use GNU, BSD, or misc. */

If gcc is invoked in its default mode, <stdlib.h> is as good as <alloca.h>
as far as alloca() is concerned.

If gcc is invoked in conforming mode, <stdlib.h> is not allowed to
declare alloca() and including said:
In any case, Dave said (incorrectly) that gcc doesn't recognize
alloca();

Dave is right, if gcc is invoked as a conforming C compiler.
In GNU C mode, gcc doesn't need any header for alloca():

fangorn:~/tmp 513> cat test.c
int main()
{
alloca();
return 0;
}
fangorn:~/tmp 514> gcc test.c
test.c: In function `main':
test.c:3: error: too few arguments to function `alloca'

gcc obviously has "insider information" about alloca in GNU C mode, since
no header has been included. OTOH, it forgets everything once invoked
in conforming mode:

fangorn:~/tmp 515> gcc -ansi test.c
/tmp/ccW0emnD.o(.text+0x11): In function `main':
: undefined reference to `alloca'
collect2: ld returned 1 exit status

Dan
 
D

Dave Vandervies

Keith Thompson said:
In any case, Dave said (incorrectly) that gcc doesn't recognize
alloca();

I didn't (or at least didn't intend to) say that; what I meant to say was
that gcc-as-a-C-compiler (as opposed to, say, gcc-as-a-Java-compiler,
or gcc-as-a-GNUC-compiler, or gcc-as-a-C++-compiler) doesn't recognize
alloca. We were talking about C here, weren't we?


dave
 
K

Keith Thompson

I didn't (or at least didn't intend to) say that; what I meant to say was
that gcc-as-a-C-compiler (as opposed to, say, gcc-as-a-Java-compiler,
or gcc-as-a-GNUC-compiler, or gcc-as-a-C++-compiler) doesn't recognize
alloca. We were talking about C here, weren't we?

Yes.

You said that a man page said that alloca() is declared in <stdlib.h>.
All the man pages I've seen say that it's declared in <alloca.h>.
Based on that, I misunderstood the point you were making. Sorry.

I also see now that gcc, in its default (non-conforming) mode, does
allow calls to alloca() when <stdlib.h> is included.

Even in conforming mode ("gcc -ansi -pedantic -Wall -W" or
"gcc -std=c99 -pedantic -Wall -W"), gcc allows calls to alloca() when
<alloca.h> is included (which is allowed because <alloca.h> is an
implementation-defined header).
 

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,054
Latest member
TrimKetoBoost

Latest Threads

Top