schwartz@swatsun.uucp (Scott Schwartz) (06/06/88)
In article <8017@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >For a limited class of applications, alloca() can be useful. >However, I don't use it myself. My applications all use a more >disciplined approach to memory allocation. One nice C extension that gcc provides is variable sized automatic arrays. I.e. foo(s) int s; { int a[s]; } I think this obviates the need for alloca() in most (all?) cases. Too late to get it in ansi, I suppose. -- Scott Schwartz, schwartz@swarthmore.edu, psuvax1!vu-vlsi!swatsun!schwartz
karl@haddock.ISC.COM (Karl Heuer) (06/06/88)
In article <1874@thebes.UUCP> schwartz@thebes.UUCP (Scott Schwartz) writes: >[gcc allows "foo(s) int s; { int a[s]; ... }".] >I think this obviates the need for alloca() in most (all?) cases. >Too late to get it in ansi, I suppose. Yes, I'm sure it's much too late to get it into ANSI C-88, if indeed it ever had a chance. But this is exactly the right way to get it into C-99 (or whenever __STDC__==2 comes out): by including it as a nonconforming extension in popular compilers, the ramifications ought to be well-understood by then. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint Followups to comp.lang.c.
david@sun.uucp (David DiGiacomo) (08/02/88)
In article <62170@sun.uucp> swilson@sun.UUCP (Scott Wilson) writes: >My main complaint with Bison was that both the source for Bison (last I >looked) and the parser it produces rely on alloca - a method for allocating >space on the stack that is automatically reclaimed when the function >that calls it exits. Alloca is found on BSD derived systems and >I am told on other UNIX's. It, however, is less than universally >available (the manual page states: "alloca() is both machine- and >compiler-dependent; its use is discouraged"). I had a rather protected >mail war with several people associated with Bison and/or FSF regarding >this. My opinion was that FSF would be doing computer users a greater >service by writing more portable code when possible. The FSF people aren't evil (?), they just disagree with the author of that man page blurb about the usefulness and implementation difficulty of alloca. By distributing excellent software which makes good use of alloca, they are ensuring that all self-respecting C compiler/library vendors will provide an efficient implementation of it. They even help out the alloca-deprived by providing Doug Gwyn's malloc based alloca. Seems reasonable to me! -- David DiGiacomo, Sun Microsystems, Mt. View, CA sun!david david@sun.com
gwyn@smoke.ARPA (Doug Gwyn ) (08/02/88)
In article <62363@sun.uucp> david@sun.uucp (David DiGiacomo) writes: >The FSF people aren't evil (?), they just disagree with the author of that >man page blurb about the usefulness and implementation difficulty of >alloca. By distributing excellent software which makes good use of >alloca, they are ensuring that all self-respecting C compiler/library >vendors will provide an efficient implementation of it. The C vendors aren't evil (?) either; requiring support for alloca() does impose an undue burden on implementations on some architectures. >They even help out the alloca-deprived by providing Doug Gwyn's malloc >based alloca. I provided that with the intention of helping people who had to import existing code that relied on alloca(), not to encourage its use in new code. In fact my emulation of alloca() can fail to reclaim free memory under some unusal circumstances. Please don't use alloca() in new code. Thanks.
swilson%thetone@Sun.COM (Scott Wilson) (08/02/88)
In article <62363@sun.uucp> david@sun.uucp (David DiGiacomo) writes: >By distributing excellent software which makes good use of >alloca, they are ensuring that all self-respecting C compiler/library >vendors will provide an efficient implementation of it. If alloca is such a wonderful function (and I'm NOT saying it isn't) then why isn't it part of the ANSI draft proposed standard libraries for C? Are you saying that a "self-respecting" C compiler/library vendor will be doing users a disservice by providing only ANSI memory routines (malloc, calloc, realloc, and free)? I would argue that it is better to conform to a standard even with its shortcomings than attempt to make something universal by "forcing" it on everyone. -- Scott Wilson arpa: swilson@sun.com Sun Microsystems uucp: ...!sun!swilson Mt. View, CA
aitken@svax.cs.cornell.edu (William Aitken) (08/02/88)
In article <8293@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: > >The C vendors aren't evil (?) either; requiring support for alloca() >does impose an undue burden on implementations on some architectures. > Could someone give a concrete example of an architecture on which alloca is difficult to implement, and explain what it is that makes automatic arrays possible, but alloca difficult? If C were to provide a means to declare an automatic array with size that depended on an integer valued argument, many of the uses of alloca would disappear; would this be any easier to implement than alloca? Why? ---- Bill. William E. Aitken <aitken@svax.cs.cornell.edu> (607)257-2542(h) {uw-beaver,ihnp4,vax135,decvax}!cornell!aitken (607)255-4222(o) aitken@crnlcs.BITNET 700 Warren Rd. #20-2A, Ithaca, NY 42 26'30" N 76 29'00" W 4148 Upson Hall
haahr@phoenix.Princeton.EDU (Paul Gluckauf Haahr) (08/03/88)
in article <19895@cornell.UUCP>, aitken@svax.cs.cornell.edu (William Aitken) writes: > Could someone give a concrete example of an architecture on which alloca is > difficult to implement, and explain what it is that makes automatic > arrays possible, but alloca difficult? in general, a compiler (rather, a run-time calling convention) that does not use a register for the frame pointer (as opposed to a virtual frame pointer) makes alloca() next to impossible. alloca() counts on being able to munge the stack frame (by adding space to it) without confusing the calling function. functions index off their frame pointers to refer to local variables, parameters, and the function return address. if the frame pointer is a real register, there is no problem: alloca() can decrement (or, rarely, increment) the stack pointer appropriately and the calling function probably won't notice. but, as is more common with newer (RISC influenced) compilers, the frame pointer is a virtual entity, really just the stack pointer plus some offset: munging the stack pointer confuses the calling function about where its locals, etc, are. Gould machines (i've heard) make it difficult to do alloca(). the MIPS R2000 normally uses a virtual frame pointer. various 68000 family compilers (at least the GreenHills compiler and Ken Thompson's 2c) do not use a register for a frame pointer, so they too probably have trouble with alloca() in the general case. many of these compilers have compile time options to force using a register as a real frame pointer, in order to allow alloca() and other stack munging. > If C were to provide a means > to declare an automatic array with size that depended on an integer valued > argument, many of the uses of alloca would disappear; would this be any > easier to implement than alloca? Why? yes, because that provides a way of telling the compiler that either it needs a real frame pointer for some particular function, or at least that some part of the stack frame is of variable length. the gnu c compiler provides this functionality. not only is easier, but notationally it is nicer, though not as general as alloca(). paul haahr princeton!haahr or haahr@princeton.edu
karl@haddock.ISC.COM (Karl Heuer) (08/03/88)
In <19895@cornell.UUCP> aitken@svax.cs.cornell.edu (William Aitken) writes: >In <8293@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >>The C vendors aren't evil (?) either; requiring support for alloca() >>does impose an undue burden on implementations on some architectures. >> >Could someone give a concrete example of an architecture on which alloca is >difficult to implement, and explain what it is that makes automatic >arrays possible, but alloca difficult? The AIX compiler on the IBM RT/PC. A single register is used for the stack pointer, frame pointer, and arg pointer; the compiler generates appropriate offsets based on its knowledge of the frame size%. If (as in the usual implementation of alloca) you tried to change the frame pointer on the fly, all hell would break lose. My conclusion (I analyzed this problem when porting GNU Emacs&, which makes heavy use of alloca) was that a proper alloca would have to be written as a compiler builtin$. In this case the cost would be one extra register, in only those functions that happen to use alloca. This doesn't seem like an undue burden. I agree with the FSF on this one. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint ________ % The frame size depends on the number of registers used by the current routine, the number of automatic variables, and the number of arguments passed to subroutines, but is independent of the number of arguments passed to the routine itself. Thus variadic functions work too. & Sorry, I'm no longer providing the Emacs diffs. They're outdated. $ I could almost have done it by postprocessing the .s file, but I couldn't find a way to get the compiler to not use all the registers.
firth@sei.cmu.edu (Robert Firth) (08/03/88)
In article <19895@cornell.UUCP> aitken@svax.cs.cornell.edu (William Aitken) writes: >Could someone give a concrete example of an architecture on which alloca is >difficult to implement, and explain what it is that makes automatic >arrays possible, but alloca difficult? If C were to provide a means >to declare an automatic array with size that depended on an integer valued >argument, many of the uses of alloca would disappear; would this be any >easier to implement than alloca? Why? First, recall that "alloca" claims a chunk of local stack space, of size unknown at compile time. It is therefore almost the same as being able to declare a local array int myarray[expression()] whose size is likewise dynamic. The implementation difficulty is almost the same. C local arrays, by contrast, have a size known at compile time, and so are a lot easier to deal with. There are two problems. Neither is really major, but they're there. First, what happens if you have an inner declaration after the allocation: int myarray[...]; /* array of dynamic size */ ... { int i,j; } If you observe strict stack allocation (LIFO) semantics, then I and J are at an offset from the start of the stack frame that you can't compute. So you have to "float" inner declarations above the dynamic declaration, which makes life tough for one-pass guys. (If you declare an inner variable after calling alloca you'll probably discover another reason why it's a bad idea to use alloca!) The second problem is that, if the size of a local stack frame is dynamic, you cannot get away with having just a frame pointer; you MUST have a stack front pointer. That can add substantially to the cost of a procedure call; moreover, it probably adds to the cost of ALL procedure calls. That means you probably can't have the caller adjust the stack, which blows away the optimisation of eliding stack adjustments between successive calls, and so compounds the inefficiency. On the majority of machines I've written codegenerators for, there is a cost in going from a stack regime where all sizes are known at compile time, to one where they aren't. It seems to me pretty silly to force every C user to pay that price for the sake of the few who regard writing portable code as beneath their dignity. So, do I have an alternative? The only serious reason for allocating dynamic objects on the local stack is to ensure their automatic deallocation on scope exit; most C dynamic storage libraries are pretty efficient. This seems to me largely a matter of programmer convenience, which could perhaps be served almost as well by an auxiliary stack managed explicitly. We initialize this by something like createaux(size) which does a malloc() to get the stack and sets up a stack pointer. We claim by allocaux(size), which grabs a chunk. We manage scopes explicitly by { m = markaux(); /* grab current aux stack pointer */ ... /* code that does a lot of allocaux() calls */ resetaux(m); /* reset aux stack pointer */ } So the programmer has to remember to set a Mark at the beginning of the scope and to do a Reset at the end of the scope. And, of course, not to jump out of the scope! Finally, there is an ALMOST safe way to do without the Mark/Reset discipline. Give each allocated chunk a header and store in it the value of the caller's stack pointer. On an allocate, first deallocate all chunks whose stored stack pointer is "below" the stack pointer of the current caller - those chunks must have passed out of scope. (I used this technique to implement Algol-60 local arrays; this was completely safe rather than "almost" safe, since the compiler could pass down to the allocator enough contextual information) Finally, the old BCPL library had a strange function that was a lot easier than alloca and allowed you to claim one (or at most a very few) chunks of stack space. It is called aptovec, and is rather like this: int aptovec( f, s ) /* whatever says f takes (*int,int) and returns int */ int s; { int myarray[s]; return f(&a[0],s); } The body is a hairy piece of machine code that achieves the above effect, including allocation and deallocation of the dynamic array. Hope this helps.
dhesi@bsu-cs.UUCP (Rahul Dhesi) (08/04/88)
In article <62363@sun.uucp> david@sun.uucp (David DiGiacomo) writes:
By distributing excellent software which makes good use of alloca,
they [FSF] are ensuring that all self-respecting C compiler/library
vendors will provide an efficient implementation of it.
The original Rationale for the design of Ada implied that the usual
mechanism for deallocating dynamically-allocated memory for a given
pointer type would be the following: All allocated memory would be
recovered when the block containing the definition of the pointer was
exited. To help this, there was a pragma that allowed the programmer
to specify how many units of memory would be needed for that pointer
type.
This sounds like exactly the type of thing alloca is good for. So I
don't think the FSF people are doing something that nobody else thought
was a good idea.
--
Rahul Dhesi UUCP: <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi
hjm@cernvax.UUCP (hjm) (08/04/88)
Two points about alloca:
- not knowing the size of the stack frames is a big pain on a non-virtual
memory machine. If a program is non-recursive, then it possible to
calculate at compile time the maximum stack usage and allocate just that
space for the stack in a multi-tasking system, minimising memory usage
and avoiding the need for stack relocation or extension.
- why have two mechanisms for memory allocation when one will do? malloc()
is perfectly adequate in that it gives you the memory you require when
you require it (if it's available) and free() lets you give it back when
you want to. Simple to implement portably, and easy to understand. If
you find it difficult to remember to give back memory at the end of a
function then why not have a function which does the following:
alloc_and_call (func, size) void (*func)(); int size;
{
char *p;
p = malloc(size);
func(p);
free(p);
}
OK, so that's not perfect. Parameter passing is a problem, but just a
small part to add on. Portable code for those people who can't remember
to deallocate stuff they asked for.
When physical memory gets tight, how do you propose that malloc and
alloca should talk to each other so that they don't tread on each other's
toes?
As a general principle, I would advocate one method for doing something rather
than two if there is any choice at all. Uniformity is something that aids
thinking and allows people to solve the real problems of writing the code to
do the job, and not to waste time wondering "should I use malloc or alloca".
Hubert Matthews
chasm@killer.DALLAS.TX.US (Charles Marslett) (08/05/88)
In article <19895@cornell.UUCP>, aitken@svax.cs.cornell.edu (William Aitken) writes: > In article <8293@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: > > > >The C vendors aren't evil (?) either; requiring support for alloca() > >does impose an undue burden on implementations on some architectures. > > > Could someone give a concrete example of an architecture on which alloca is > difficult to implement, and explain what it is that makes automatic > arrays possible, but alloca difficult? The only reasonable way to allocate a variable amount of space from the stack is to maintain a register (or local memory cell) containing the size or end of the allocated space -- on some computers this is provided "free of charge" by the architecture (so we use it) and on others it imposes overhead on subroutine call/return linkage, usually serious only for very short routines (and we do not use it). A second and much more serious problem is that many of us are forced to use Intel based boxes with 64K stacks and code using alloca() often allocates too much local memory. Malloc() on the other hand can always allocate 64K per chunk and often (MSC under DOS for example) can allocate any size up to the hardware available. Of course, sloppy programmers then have to remember to free what they allocated -- I find this can help document the routine as well (named braces would help even more, oh well . . .). > ... If C were to provide a means > to declare an automatic array with size that depended on an integer valued > argument, many of the uses of alloca would disappear; would this be any > easier to implement than alloca? Why? See comments above: both problems would remain (except that a mechanism could probably be built into Intel C compilers to allcoate arrays off a second "software" stack -- compilers for the 6502 often do this). Does anyone know of an alloca() implementation that works this way -- other than Doug Gwen's (and I would like to see it as well). > ---- Bill. > William E. Aitken <aitken@svax.cs.cornell.edu> (607)257-2542(h) > {uw-beaver,ihnp4,vax135,decvax}!cornell!aitken (607)255-4222(o) > aitken@crnlcs.BITNET 700 Warren Rd. #20-2A, Ithaca, NY > 42 26'30" N 76 29'00" W 4148 Upson Hall Charles Marslett chasm@killer.dallas.tx.us STB Systems, Inc. (2140 234-8750
meissner@xyzzy.UUCP (Michael Meissner) (08/12/88)
In article <62412@sun.uucp> swilson@sun.UUCP (Scott Wilson) writes: | If alloca is such a wonderful function (and I'm NOT saying it isn't) | then why isn't it part of the ANSI draft proposed standard libraries | for C? Are you saying that a "self-respecting" C compiler/library | vendor will be doing users a disservice by providing only ANSI memory | routines (malloc, calloc, realloc, and free)? I would argue that it | is better to conform to a standard even with its shortcomings than | attempt to make something universal by "forcing" it on everyone. It was proposed to the ANSI committee, and it got shot down, for two reasons: 1) it was judged to be too late; 2) the systems don't have frame pointers on their stacks would have to recognize it as a builtin and support it through some method. -- Michael Meissner, Data General. Uucp: ...!mcnc!rti!xyzzy!meissner Arpa: meissner@dg-rtp.DG.COM (or) meissner%dg-rtp.DG.COM@relay.cs.net
U23405@UICVM (Michael J. Steiner) (08/17/88)
Note: The following is only my opinion, not a research summary or survey results. :-) In my opinion, I have a slight aversion to using machine-dependent code, including #if's, bit operations, and #asm. I am against using alloca() because malloc() and calloc() are supported by more compilers, easier to support on most machines than alloca(), and because the free()'s that must accompany the use of malloc() or calloc() help to document the code (e.g. remind the programmer of what he will lose when the function terminates). Also, someone's argument that using both malloc() and alloca() may lead to memory conflicts is a good reason to only use malloc() or calloc(). I generally try to do a programming task using the standard (noncontroversial) concepts in C. However, if using #if or alloca() (etc.) is the only way to do a task (or if not using it would make the code less understandable), and your compiler supports it, and you document your usage of these controversial concepts (items?), then I have no complaint. However, most of my programming assignments so far have not been in writing compilers, OS's, or other "hard" software, so I haven't had the need to use these things. Michael Steiner Email: U23405@UICVM
smryan@garth.UUCP (Steven Ryan) (08/19/88)
Just to keep this fight going..... I grew up with Algol 60, where dynamic bounds on arrays provide the equivalent of alloca(). I assumed Pascal's nonsense was something everybody would recognise as stupid and the next group would take care of. Oh, well. I couldn't care less about losing one register just to get back dynamic arrays. (While heap storage includes local storage, heaps are almost always slower; using an indirect address instead of a stack base+offset screws up the optimiser; remember to release everything at the end screws up the programmer. Local storage is a no-fuss, no-bother, no-problem solution to a need I have in near most every program I write.)
chasm@killer.DALLAS.TX.US (Charles Marslett) (08/20/88)
In article <1259@garth.UUCP>, smryan@garth.UUCP (Steven Ryan) writes: > Just to keep this fight going..... > > I grew up with Algol 60, where dynamic bounds on arrays provide the > equivalent of alloca(). I assumed Pascal's nonsense was something > everybody would recognise as stupid and the next group would take care > of. > > Oh, well. > > I couldn't care less about losing one register just to get back dynamic > arrays. (While heap storage includes local storage, heaps are almost > always slower; using an indirect address instead of a stack base+offset > screws up the optimiser; remember to release everything at the end > screws up the programmer. Local storage is a no-fuss, no-bother, no-problem > solution to a need I have in near most every program I write.) I have seen this point made many, many times in the "alloca" discussion -- and (having both used very good compilers and written mediocre ones) I find it hard to believe you believe this. (1) Heaps are in fact almost always slower than "alloca" -- and they are almost always more versatile and only rarely do I need to allocate enough items that the speed difference is important. And then, the speed I gain using fixed (static or automatic) arrays beats alloca all round the block. (2) Any alloca implementation that creates an base+offset reference to the dynamic stack allocation (for more than 1 alloca call, that is) appears to me to be no more efficient than the equivalent registered pointer variable (and just as hard to optimize). (3) As far as ignoring the task of freeing memory -- I would not do this even were I using alloca -- this ties the structure of the problem code to a detail of the computer architecture (as has been mentioned several times before) and the detail is very much tied to traditional CISC architecture (that is a single big general purpose stack that is freely addressable). Many studies show this to be a poor use of resources (stack access is heavily skewed to the top few locations, and register systems usually outperform stack systems when relativly good compilers are involved). Some (many?) RISC processors use sliding stack frames and high overhead software stacks to take advantage of these characteristics but in the process make alloca code slow and error prone. Note I did not say impossible, just not efficient (and that is the only claim to fame I really admit for alloca in the first two points). Actually, this should probably all be carried on in the comp.philosopy.d newsgroup (is there one?). And I have rambled on too long, just like this discussion (`^}] . . . Charles Marslett <--- a lover of symmetry STB Systems, Inc <--- where they don't even use malloc (often) chasm@killer.dallas.tx.us <--- where I usually get flamed (deservedly)
jbs@fenchurch.MIT.EDU (Jeff Siegal) (08/20/88)
In article <1259@garth.UUCP> smryan@garth.UUCP (Steven Ryan) writes:
[...](While heap storage includes local storage, heaps are almost
always slower; using an indirect address instead of a stack base+offset
screws up the optimiser; remember to release everything at the end
screws up the programmer. Local storage is a no-fuss, no-bother, no-problem
solution to a need I have in near most every program I write.)
Take a look at Scheme.
Jeff Siegal
smryan@garth.UUCP (Steven Ryan) (08/21/88)
>(1) Heaps are in fact almost always slower than "alloca" -- and they are > almost always more versatile and only rarely do I need to allocate > enough items that the speed difference is important. And then, the > speed I gain using fixed (static or automatic) arrays beats alloca > all round the block. I frequently write procedures for a fixed graph. Putting all the nodes in a random addressable array instead of linked list frequently reduces the time complexity by a factor of n. I can't use fixed size arrays because I do not know the size of graph ahead of time. I know how to use malloc to allocate space on the heap but the results are ugly, require explicit free, and intrinsically slower. Some of us write programs other people use and time and space not trivial concerns. >(2) Any alloca implementation that creates an base+offset reference to > the dynamic stack allocation (for more than 1 alloca call, that is) > appears to me to be no more efficient than the equivalent registered > pointer variable (and just as hard to optimize). No, it is easier to optimise if it is known that a pointer is constrained to a specific region [of the local stack]. This has to do with aliassing and ref/defs. >(3) As far as ignoring the task of freeing memory -- I would not do this > even were I using alloca -- this ties the structure of the problem > code to a detail of the computer architecture (as has been mentioned > several times before) and the detail is very much tied to traditional > CISC architecture (that is a single big general purpose stack that is I don't understand: the concept of a single big general purpose stack is fundamental to any language that implements recursion. The automatic release of locally generated space is semantically identical to the automatic release of local variable. Now if you're saying it's a problem trying to graft in local allocation into a compiler which does provide the appropriate interfaces, undoubtably right. I don't think it should be a graft. Aw, but if it were part of the language. All hope is not lost: many implementors have added dynamic arrays to Fortran.
smryan@garth.UUCP (Steven Ryan) (08/21/88)
>Take a look at Scheme.
Eh? Summary, please?
scjones@sdrc.UUCP (Larry Jones) (08/22/88)
Just to confuse the discussion further, what about machines / operating systems which do not have a stack? It is perfectly reasonable to support recursion by explicitly allocating heap memory to hold local variables on entry to the function and freeing it on exit. To support alloca in this type of system requires reallocating the block (which may mean allocating a new, bigger block and copying the old block into it, except that would screw up pointers...) or maintaining a linked list of blocks. Seems like an awful lot of overhead to avoid writing a couple of calls to free(). ---- Larry Jones UUCP: uunet!sdrc!scjones SDRC scjones@sdrc 2000 Eastman Dr. BIX: ltl Milford, OH 45150 AT&T: (513) 576-2070 Nancy Reagan on superconductivity: "Just say mho."
jbs@fenchurch.MIT.EDU (Jeff Siegal) (08/22/88)
In article <1271@garth.UUCP> smryan@garth.UUCP (Steven Ryan) writes: >>Take a look at Scheme. >Eh? Summary, please? Sorry. Scheme is a lexically scoped LISP dialect, implementations of which often place environments (local variable bindings) on a stack rather than the heap (when possible). This can give you both the generality of a heap and the efficiency of a stack. It is also interesting (although unrelated) that implementations of Scheme are encouraged to support tail-recursion efficiently, making it the priamary iterative mechanism. Jeff Siegal
smryan@garth.UUCP (Steven Ryan) (08/23/88)
>screw up pointers...) or maintaining a linked list of blocks. Seems like >an awful lot of overhead to avoid writing a couple of calls to free(). I once heard of a description of difference between pascal and algol68: - pascal does the easy parts and lets the programmers do the hard parts. - algol68 does the hard parts and lets the programmers do the easy parts.
les@chinet.UUCP (Leslie Mikesell) (08/23/88)
In article <355@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes: > >Just to confuse the discussion further, what about machines / operating >systems which do not have a stack? [ description deleted] >..... Seems like >an awful lot of overhead to avoid writing a couple of calls to free(). Well, your description of the thing you wish to avoid pretty much fits the way malloc() usually works. But the real problem is that to make those calls to free() you must unwind the stack under all conditions. If the memory is released like automatic variables, you can longjmp() out of a signal handler or a lower level function and get back to a known condition. Les Mikesell
mouse@mcgill-vision.UUCP (der Mouse) (08/23/88)
In article <355@sdrc.UUCP>, scjones@sdrc.UUCP (Larry Jones) writes: > Just to confuse the discussion further, what about machines / > operating systems which do not have a stack? I would expect an implementation of C on such a machine to provide a stack, implemented in software to the extent that it isn't supported by the hardware. Not that it must, of course; I can imagine a C compiler for a Lisp Machine which doesn't put automatics on the stack. But I would be somewhat surprised to find one that didn't. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
chasm@killer.DALLAS.TX.US (Charles Marslett) (08/24/88)
In article <1257@mcgill-vision.UUCP>, mouse@mcgill-vision.UUCP (der Mouse) writes: > In article <355@sdrc.UUCP>, scjones@sdrc.UUCP (Larry Jones) writes: > > Just to confuse the discussion further, what about machines / > > operating systems which do not have a stack? > > I would expect an implementation of C on such a machine to provide a > stack, implemented in software to the extent that it isn't supported by > the hardware. Not that it must, of course; I can imagine a C compiler > for a Lisp Machine which doesn't put automatics on the stack. But I > would be somewhat surprised to find one that didn't. > Actually I have programmed using two C compilers for the 6502 and one I consider a REAL TOY (I wish I could emphasize that even more) just because it did put automatic variables on the stack -- all 256 bytes of it! The other had return addresses only on the hardware stack and if I remember correctly, only put automatic variables on a seperate software stack if the function was called recursively because of the excessive overhead involved in copying the entire data area to and from the stack each time the function was called. So recursive routines used two stacks, non- recursive ones used one and in no case were automatic variables actually used on the stack. I might also ask, "Do sliding frame RISC machines have any C compilers that work similarly?" Or do they shuffle the frame to and from the memory stack without reference to structure? > der Mouse > a (former) 6502 c programmer Charles Marslett chasm@killer.dallas.tx.us
news@amdcad.AMD.COM (Network News) (08/24/88)
In article <5281@killer.DALLAS.TX.US> chasm@killer.DALLAS.TX.US (Charles Marslett) writes: | So recursive routines used two stacks, non- | recursive ones used one and in no case were automatic variables actually | used on the stack. | | I might also ask, "Do sliding frame RISC machines have any C compilers that | work similarly?" Or do they shuffle the frame to and from the memory stack | without reference to structure? The Am29000 calling convention uses two stacks -- the memory stack and the register stack. Local scalar variables, return addresses, and the first 16 words of parameters are stored on the register stack, the top of which is cached on chip in the register file. Non-scalar (large arrays & structs) data is stored on the memory stack. -- Tim Olson Advanced Micro Devices (tim@delirun.amd.com)
peter@ficc.uu.net (Peter da Silva) (08/25/88)
The basic problem is that alloca doesn't handle unwinding anything but memory. Here's a bare-bones exception handling system. Suitable macros can make it as ADA-like as you can stand. For systems with decent signal handling (like, I believe, BSD) wrap the critical sections in appropriate signal protection code. Do this, and any errors will bubble up the call chain completely safely. struct jmp_buf error; someroutine() { struct jmp_buf old_error; struct foo *bar; int code; bar = 0; old_error = error; if(code = setjmp(error)) { if(bar) free(bar); error = old_error; longjmp(error, code); } bar = malloc(sizeof *bar); if(!bar) { error = old_error; longjmp(error, ENOMEM); } body of routine free(bar); error = old_error; return 0; } -- Peter da Silva `-_-' Ferranti International Controls Corporation. "Have you hugged U your wolf today?" sugar.uu.net!ficc!peter.
ssuhook@rosemary.cs.reading.ac.uk (Roger Neil Hook) (08/18/90)
I am trying to compile GNU bison version 1.10 on a PC running DOS 3.3, using Turbo C v2.0. The source references a function called 'alloca' to allocate memory off the stack which is automatically freed when the function calling it returns. 'alloca' is not included in the TurboC library, and is anyway not standard C. I have come across two sets of assembly sources for a __680x0__ version, but do not understand precisely how they function, not having much experience in assembly. Turbo C describes two methods of calling C functions which it calls 'cdecl' and 'pascal' conventions. I have been trying to work out how to write an 80x86 assembly version of alloca to work with Turbo C. The problems I have encountered relate to not understanding what the conventions for calling a function are, and also confusion arising from trying to work out what the stack pointer is doing. To whit: I assume it is possible for a C compiler (on a PC but not necessarily TurboC) to have a function, say A(), which does some stuff which ends up with data stored on the stack. Then it calls alloca() which I assume modifies the stack pointer to hide the alloca'd block. 1) This being the case, how does A find it's stacked data? 2) Also how does the memory get freed? 3) How can I write a version of alloca in 8086 assembly for the PC, and TurboC in particular? 4) Finally, could someone please explain what alloca _should_ do, and also what the version below (extracted from a GNU library for the Atari GCC) does, especially the last op: .text .even .globl _alloca _alloca: movel sp@+,a0 ;get return addr movel sp@+,d0 ;get size -- assist in bug fix, add 4 to sp addql #1,d0 ;ensure address even andl #0xFFFFFFFE,d0 ;lop off extra bits subl d0,sp ;increase stack frame size by that much movel sp,d0 ;set up to return it lea sp@(-4),sp ;new top of stack (real bug fix here) jmp a0@ ;return by jumping via saved addr In summary, I am mainly interested in finding out how to get an alloca() for the PC for Turbo C, and also what it is that alloca() actually does. My apologies in advance if bits of this aren't relevant to any particular group. Please email me, and I will endeavour to summarize to the net if there is enough interest. Thanks, Alias JANET: ssuhook@susssys1.rdg.ac.uk
vu0310@bingvaxu.cc.binghamton.edu (R. Kym Horsell) (08/18/90)
In article <2745@onion.reading.ac.uk> ssuhook@susssys1.cs.reading.ac.uk writes: \\\ >In summary, I am mainly interested in finding out how to get an alloca() for >the PC for Turbo C, and also what it is that alloca() actually does. \\\ Alloca does something *like* char *alloca(n) { n = /* round up to words */; ((char*)SP) += n; /* bump up the stack ptr */ return (char*)SP-n; /* return address of stuff on stack */ } I.e. it just bumps up the stack by n bytes (usually word alignining the result) and returns the address of the new stack section. Since the SP is restore by C exit stuff from a `frame ptr register' (typically, anyway) this memory is deallocated at the end of the function. Note I've assumed the stack grows up (not a normal thing these days). Also we can't *actually* write alloca() as above even when you can refer to the SP directly since its exit will deallocate the space just allocated -- you should think of alloca() as written above as a macro. To solve your problem with proting Bison -- why not use (a) malloc/alloc and just forget deallocating it, or (b) malloc/alloc and use an explicit free at the end of the function its used it (might as well catch *all* returns from the function while you're about it). Ive written a fairly complete Yacc/Lex for AT's and didn't both about memory leakage. After a PDP-11 there was more memory than I new what to do with (ahhh...many years ago now). Hope this's been some help, -Kym Horsell
trier@cwlim.CWRU.EDU (Stephen C. Trier) (08/22/90)
Here's a version of alloca I use. It's my clone of a version from some piece of PD software I saw a year or two ago. #define alloca(A) ((_SP -= ((A)+1) & 0xFFFE), (void far *)(((unsigned long)_SS << 16) | _SP)) The idea is to subtract the size A from the stack pointer, making sure it's word-aligned. (This is the (_SP -= ((A)+1) & 0xFFFE) part.) Then, since alloca returns a pointer to the allocated space, the macro must kludge together a far pointer from the stack segment and stack pointer. I should add the disclaimer that I'm not entirely sure that this works. It's my own version of someone else's, but I changed it a bit. (I don't remember what the original looked like.) Hope this helps! -- Stephen Trier Case Western Reserve University Home: sct@seldon.clv.oh.us Information Network Services Work: trier@cwlim.ins.cwru.edu I may work for the University, but that doesn't mean I speak for them.
sidney@saturn.ucsc.edu (Sidney Markowitz ) (08/23/90)
trier@po.CWRU.Edu writes: >Here's a version of alloca I use. It's my clone of a version from some >piece of PD software I saw a year or two ago. [For anyone who still hasn't gotten the idea, alloca is supposed to allocate storage (like malloc) which is automatically freed upon exit from the calling procedure (as if they are on the stack like local variables).] I haven't checked it out thoroughly in TC 2.0, but in TC++ nothing that actually puts the alloca'd storage on the stack is going to work. For one thing, the compiler may save a value on the stack before the call to alloca, then try to pop it after the call, not realizing that alloca has changed the stack. Also, if you look at the assembler code generated for a function that has 0, 1 or 2 words of local variables, you will see that no stack space is reserved for them (SI and DI registers are used instead) and the compiler assumes that it doesn't need a mov sp,bp instruction to restore the stack on exit. This assumption is not true if alloca has pushed stuff on the stack expecting it to be cleaned up on exit. Basically, you can't have a real alloca without support from the compiler. There's a portable alloca written in C that I've seen with some FSF software. It simulates the effect of alloca by calling malloc and maintaining a linked list of pointers to the allocated blocks, along with the value of SP at the time of each allocation. Whenever alloca is called, it goes through the linked list, freeing all blocks for which the saved SP is smaller (deeper in the stack) than the current one. So alloca'd storage is not freed at once upon exit from the routine that is calling alloca, but instead is freed approximately the next time alloca is called. If there is interest, I can post the code. But I suggest rewriting the program to use malloc and free instead of alloca. -- sidney markowitz <sidney@saturn.ucsc.edu>
dale@NCoast.ORG (Dale Smith) (08/23/90)
In article <1990Aug22.032243.18214@usenet.ins.cwru.edu> trier@po.CWRU.Edu writes: >Here's a version of alloca I use. It's my clone of a version from some >piece of PD software I saw a year or two ago. > > #define alloca(A) ((_SP -= ((A)+1) & 0xFFFE), (void far *)(((unsigned long)_SS << 16) | _SP)) > >The idea is to subtract the size A from the stack pointer, making sure >it's word-aligned. (This is the (_SP -= ((A)+1) & 0xFFFE) part.) Then, >since alloca returns a pointer to the allocated space, the macro must >kludge together a far pointer from the stack segment and stack pointer. > >I should add the disclaimer that I'm not entirely sure that this works. >It's my own version of someone else's, but I changed it a bit. (I don't >remember what the original looked like.) > >Hope this helps! > >-- >Stephen Trier Case Western Reserve University >Home: sct@seldon.clv.oh.us Information Network Services >Work: trier@cwlim.ins.cwru.edu > I may work for the University, but that doesn't mean I speak for them. I believe I saw something like that in an early port of bison. It's really cute but will trash register variables. Someone posted an alloca for the 386 which I hacked to fit Turbo C. I also took a peek at a disassembly of the Microsoft C 5.1 alloca(). Here it is, have fun. ------ Snip it or somethin' ------------------------------ ; alloca.asm ; Allocate from the stack for Turbo C 2.0 ; I have not tried this this TC++ 1.0 ; void *alloca(size_t size); ; Beware of using alloca in functions without arguments ; and -k- in tiny, small, and medium models. The stack has a ; possibility of growing. ifdef __TINY__ .model tiny elseifdef __SMALL__ .model small elseifdef __MEDIUM__ .model medium elseifdef __COMPACT__ .model compact elseifdef __LARGE__ .model large elseifdef __HUGE__ .model huge else .model small endif if @DataSize EQ 0 .data extrn ___brklvl:word endif .code public _alloca _alloca proc ;; Pop return address into (es:) cx and size into ax pop cx ; return address if @CodeSize pop es ; return segment endif pop ax ; size ;; Make sure that ax is greater than zero, and is a multiple of two. cmp ax,0 jl error inc ax and ax,not 1 ;; Figure new stack pointer, check for negative and less than brk. mov bx,sp sub bx,ax jb error ; below zero if @DataSize EQ 0 ; tiny, small, medium cmp bx,___brklvl jb error ; below the brk endif xchg sp,bx mov ax,sp ;; Copy the (hypothetical) register variables. ifdef __MEDIUM__ push ss:6[bx] ; return segment(medium) endif push ss:4[bx] ; return offset(med,sm,tiny) or ds(huge) push ss:2[bx] ; di (all) push ss:[bx] ; si (all) if @DataSize mov dx,ss endif exit: ;; Put something on the stack so that our caller can pop it off. push ax ;; Return to the the caller. if @CodeSize push es push cx ret else jmp cx endif error: xor ax,ax if @DataSize cwd endif jmp exit endp end -------------- Ok, that's it ----------------------------------------- dale -- Dale P. Smith dale@ncoast.org uunet!usenet.ins.cwru.edu!ncoast!dale
pruss@ria.ccs.uwo.ca (Alex Pruss) (08/28/90)
In article <1990Aug22.032243.18214@usenet.ins.cwru.edu> trier@po.CWRU.Edu writes: >Here's a version of alloca I use. It's my clone of a version from some >piece of PD software I saw a year or two ago. > > #define alloca(A) ((_SP -= ((A)+1) & 0xFFFE), (void far *)(((unsigned long)_SS << 16) | _SP)) This looks surprisingly like the original of my alloca(). Unfortunately it doesn't work. (Not at all!--my version didn't either--it took many hours of painful debugging to find what was wrong.) You see it returns SS:SP. However, next time a function call, push, or interrupt comes along, a word gets stored at SS:SP which is part of the allocated area. Thus a minimal fix is to change it to: #define alloca(A) ((_SP -= ((A)+1) & 0xFFFE), (void far *)(((unsigned long)_SS << 16) | _SP+2)) Unfortunately this fails in the case that the function has stored DS/SI/DI on the stack. Furthermore one must beware that the calling function may not have a proper stack frame. >I should add the disclaimer that I'm not entirely sure that this works. >It's my own version of someone else's, but I changed it a bit. (I don't >remember what the original looked like.) It was less elegant in the forcing of A to be even, and it too didn't work. It included also a { char dummy; dummy=dummy; } type of thing to force a stack frame. Anyways, the latest WORKING (I hope... I tested it...) version I've just posted to alt.sources. (The whole thing with docs and uuencoded object files is 13Kb, so I didn't want to post it here). pruss@uwo.ca // internet pruss@uwovax // bitnet pruss@ria // uucp //\\ The SCHSPH Guy //\\
russ@groucho.ucar.edu (Russ Rew) (11/02/90)
Comments in Doug Gwyn's "(mostly) portable public-domain implementation" of alloca say It should work under any C implementation that uses an actual procedure stack (as opposed to a linked list of frames). What common platforms do not provide an alloca or cannot use Doug Gwyn's alloca because they don't use a procedure stack? In other words, if we decide to use alloca despite the warnings about its portability, what platforms are we precluding? Reply by mail, and I'll summarize. Russ Rew Unidata Program Center russ@unidata.ucar.edu Russ Rew Unidata Program Center russ@unidata.ucar.edu UCAR, P.O. Box 3000 (303) 497-8845 Boulder, CO 80307-3000
steve@taumet.com (Stephen Clamage) (11/03/90)
russ@groucho.ucar.edu (Russ Rew) writes: >Comments in Doug Gwyn's "(mostly) portable public-domain implementation" of >alloca say > It should work under any C implementation that uses an > actual procedure stack (as opposed to a linked list of > frames). >What common platforms do not provide an alloca or cannot use Doug Gwyn's >alloca because they don't use a procedure stack? In other words, if we >decide to use alloca despite the warnings about its portability, what >platforms are we precluding? There is more to it than the target machine. Some compilers get a performance win by omitting frame pointers and leveling the stack only when actually needed. The compiler keeps track of the top of the stack, and parameter and local variable references are relative to the current TOS rather than to the FP. Upon return from a function, the stack is not necessarily popped -- it gets leveled only when different flow paths converge. With such a stack management strategy, alloca cannot be implemented as a library routine -- it would have to be built into the compiler. -- Steve Clamage, TauMetric Corp, steve@taumet.com
karl@ima.isc.com (Karl Heuer) (11/05/90)
In article <499@taumet.com> steve@taumet.com (Stephen Clamage) writes: >russ@groucho.ucar.edu (Russ Rew) writes: >>[Are there any real implementations where Doug Gwyn's alloca() fails?] >There is more to it than the target machine. Some compilers get a >performance win by omitting frame pointers ... Irrelevant. The Gwyn alloca() doesn't use the algorithm of moving the frame pointer and jumping back to the caller; it's written in C, and I've used it on systems where the assembly version can't work for the reasons stated. In response to the original question: it might conceivably fail on a system that does strict pointer checking (Sabre). Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint
gwyn@smoke.brl.mil (Doug Gwyn) (11/07/90)
In article <499@taumet.com> steve@taumet.com (Stephen Clamage) writes:
-There is more to it than the target machine. Some compilers get a
-performance win by omitting frame pointers and leveling the stack only
-when actually needed. The compiler keeps track of the top of the
-stack, and parameter and local variable references are relative to the
-current TOS rather than to the FP. Upon return from a function, the
-stack is not necessarily popped -- it gets leveled only when different
-flow paths converge. With such a stack management strategy, alloca
-cannot be implemented as a library routine -- it would have to be built
-into the compiler.
But that doesn't adversely affect my alloca() strategy.
It is worth repeating over and over: DON'T WRITE CODE THAT USES alloca()!
I provided my alloca() implementation solely in support of existing code
that needs to be ported and for which fixing its use of alloca() would be
too painful.
steve@groucho.ucar.edu (Steve Emmerson) (11/08/90)
In <14377@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >It is worth repeating over and over: DON'T WRITE CODE THAT USES alloca()! But why? You yourself admitted that systems on which your alloca() couldn't work are few and far between. Not a challenge, just an inquiry. Steve Emmerson steve@unidata.ucar.edu ...!ncar!unidata!steve
chris@mimsy.umd.edu (Chris Torek) (11/08/90)
In article <9122@ncar.ucar.edu> steve@groucho.ucar.edu (Steve Emmerson) asks: >[Why not use alloca? Doug Gywn] admitted that systems on which [his] >alloca() couldn't work are few and far between. There are two reasons people use alloca() instead of malloc(). One is that alloca()'ed space goes away automatically. Doug Gwyn's implementation sometimes manages to achieve this, and even if not, it at least gets the code to run until all memory has been consumed. The other reason people use alloca() instead of malloc() is that it is more efficient. Since the `semi-portable' alloca() calls malloc(), the `it can be done' argument destroys the `it is more efficient' argument for these machines. The efficiency argument still holds on other machines. Unfortunately, on these machines, the source code foo(int n) { char *p = alloca(n); munge(p, n); /* munge needs n bytes of temporary space */ } (which appears likely to work) is quite likely to be compiled as foo(int n) { munge(alloca(n), n); } which is in fact fairly unlikely to work (it fails on, for instance, a VAX). To make it work, either we have to either produce suboptimal code for bar(int n) { char *p = jiggle(n); munge(p, n); } (which should in fact be compiled without the temporary) or else we have to gimmick the compiler to know about alloca(). (GCC 1.37.1 on a VAX produces the suboptimal code. The version without `p' uses r0 to hold n; the one with p uses r6, necessitating a push and pop during entry to and exit from bar().) The latter is medium-difficult but is in fact the only approach that is guaranteed always to work (provided, of course, that the compiler- gimmicking is done correctly). Since the ANSI standard does not *require* this, and since alloca() is little-used, it is not all that likely that most compiler vendors will do this. So we can say that, where alloca is more efficient than malloc, it is not safe (because optimising compilers may `move' calls to alloca so that they are made when the stack is not in its canonical format). Where alloca is not more efficient (because we have to use Doug Gywn's version or something equivalent), it is slightly more convenient. It is also at least slightly less portable. All in all, I would say that the threat of failure (from optimizing compilers) plus that of nonportability (to environments where not even a mallocking alloca can be used) far outweigh the convenience of not having to call free(). All that is left is the difference in speed, and there are simple ways around that problem as well. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
jtc@van-bc.wimsey.bc.ca (J.T. Conklin) (11/09/90)
In article <14377@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >It is worth repeating over and over: DON'T WRITE CODE THAT USES alloca()! >I provided my alloca() implementation solely in support of existing code >that needs to be ported and for which fixing its use of alloca() would be >too painful. I agree that alloca() should not be used, but sometimes the low overhead of alloca(), especially when implemented as a compiler builtin, is just too good to pass up. In the cases were you feel you can't live without alloca(), I suggest something like this: #ifdef HAVE_WORKING_ALLOCA #define ALLOCATE_LOCAL(n) alloca(n) #define DEALLOCATE_LOCAL(m) #else #define ALLOCATE_LOCAL(n) malloc(n) #define DEALLOCATE_LOCAL(m) free(m) void foo(int bar) { char *s = ALLOCATE_LOCAL(bar); ... DEALLOCATE_LOCAL(s); return; } Make sure there is a DEALLOCATE_LOCAL() call before every point of exit from your function, and you won't have any memory leaks. I think this technique is used in the X Window sample servers. --jtc -- J.T. Conklin UniFax Communications Inc. ...!{uunet,ubc-cs}!van-bc!jtc, jtc@wimsey.bc.ca
gwyn@smoke.brl.mil (Doug Gwyn) (11/09/90)
In article <9122@ncar.ucar.edu> steve@groucho.ucar.edu (Steve Emmerson) writes: >In <14377@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >>It is worth repeating over and over: DON'T WRITE CODE THAT USES alloca()! >But why? You yourself admitted that systems on which your alloca() >couldn't work are few and far between. Because it's not needed, so why ask for problems? When there are strictly conforming methods to achieve your ends, you should use them, because probably some day some poor slob is going to have to port your code to a radically different architecture, and the Golden Rule says you shouldn't make his life miserable.
les@chinet.chi.il.us (Leslie Mikesell) (11/10/90)
In article <27537@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes: >All in all, I would say that the threat of failure (from optimizing >compilers) plus that of nonportability (to environments where not even >a mallocking alloca can be used) far outweigh the convenience of >not having to call free(). All that is left is the difference in >speed, and there are simple ways around that problem as well. The usual "simple" way goes something like this: #define BIG_BUFF 1024 /* that should be big enough */ work(str) char *str; { buffer[BIG_BUFF); strcpy(buffer,str); /* make a local copy to manipulate */ .... } This does handle recursion and longjmp()'s out of signal handlers with a lot less work than a malloc() based solution and it could even be kept from crashing at random if a length check were added, but there is no guarantee that an entire string can be manipulated. It just leaves the nagging feeling that something necessary was omitted from the language.... The argument that alloca isn't a requirement because it's little-used (and it's little-used because its not required) doesn't help much either. Les Mikesell les@chinet.chi.il.us
scs@adam.mit.edu (Steve Summit) (11/10/90)
In article <1990Nov7.234315.15508@athena.mit.edu> I wrote: >Correction: "If you just want the pointer to be around during the >function and you want the program to be unportable..." [use alloca] In article <3729@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes: >Where unportable means "portable to an extremely large class of >machines and compilers". Portability is always a compromise. You >have the choice of rejecting machines or compilers with such serious >deficiencies as making alloca() impossible. Not everyone views such machines and compilers as deficient, let alone seriously so. Followups to alt.religion.computers. Steve Summit scs@adam.mit.edu
net@opal.cs.tu-berlin.de (Oliver Laumann) (11/11/90)
In article <1990Nov09.233527.7489@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes: > The usual "simple" way goes something like this: > > #define BIG_BUFF 1024 /* that should be big enough */ > > work(str) > char *str; > { > buffer[BIG_BUFF); > strcpy(buffer,str); /* make a local copy to manipulate */ This, of course, doesn't work when the amount of data to be stored in the local buffer can't be determined at compile time. If it were known at compile time, there would be no need to use alloca() in the first place. -- Oliver Laumann net@TUB.BITNET net@tub.cs.tu-berlin.de net@tub.UUCP
avery@netcom.UUCP (Avery Colter) (11/11/90)
russ@groucho.ucar.edu (Russ Rew) writes: >What common platforms do not provide an alloca or cannot use Doug Gwyn's >alloca because they don't use a procedure stack? In other words, if we >decide to use alloca despite the warnings about its portability, what >platforms are we precluding? Well, ORCA/C is supposedly ANSI rated, and there is no alloca command that I can see. There is the function malloc, and a proviso that says that a coding of the old calloc command will in ORCA/C be macroed into malloc. What exactly were the syntax, parameters, and usage of this alloca? -- Avery Ray Colter {apple|claris}!netcom!avery {decwrl|mips|sgi}!btr!elfcat (415) 839-4567 "Fat and steel: two mortal enemies locked in deadly combat." - "The Bending of the Bars", A. R. Colter
gwyn@smoke.brl.mil (Doug Gwyn) (11/11/90)
In article <1990Nov09.233527.7489@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes: >The argument that alloca isn't a requirement because it's little-used >(and it's little-used because its not required) doesn't help much either. This must be a matter of attitude or something of the sort. In literally hundreds of thousands of lines of C applications code, I have NEVER needed alloca(), and I certainly do worry about such things as artificial limits on the sizes of strings that can be handled.
chris@mimsy.umd.edu (Chris Torek) (11/12/90)
In article <1990Nov09.233527.7489@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes, not in quite this order: >This does handle recursion and longjmp()'s out of signal handlers As soon as you mention `longjmp out of signal handlers' you have left either portability or reliability far behind (even if you are careful, doing *anything* with signals tends to make software unportable). In article <27537@mimsy.umd.edu> I wrote: >>All in all, I would say that the threat of failure (from optimizing >>compilers) plus that of nonportability (to environments where not even >>a mallocking alloca can be used) far outweigh the convenience of >>not having to call free(). All that is left is the difference in >>speed, and there are simple ways around that problem as well. >The usual "simple" way goes something like this: > >work(str) >char *str; >{ > buffer[BIG_BUFF]; > strcpy(buffer,str); /* make a local copy to manipulate */ No, actually, I was thinking of one of these: void foo(int n) { static char *space; static size_t size; size_t need = compute_space_needed(n); if (size < need) { space = space ? realloc(space, need) : malloc(need); if (space == NULL) ... handle no space ... size = need; } ... } or void foo(int n) { char *space; size_t need = compute_space_needed(n); char local[SMALL]; if (need <= SMALL) space = local; else { space = malloc(need); if (space == NULL) ... handle no space ... } ... cannot simply `return' here ... if (space != local) /* equiv, need > SMALL */ free(space); } >[Using alloca()] does handle recursion The second form above handles recursion; the first does not, but is more efficient in some cases, and is somewhat easier to code (since all the allocation goes in one place). A third form, in which the caller provides the space and there is a wrapper function that uses either the local buffer or space from malloc(), is of course possible. >and longjmp()'s out of signal handlers (I consider this not worth much in most programs. Only in very restricted circumstances does this become valuable. Rarely, it *does* become very valuable; then the tradeoffs shift.) >with a lot less work than a malloc() based solution >It just leaves the nagging feeling that something necessary was omitted >from the language.... Quite possibly. See Dennis Ritchie's proposed variable-sized arrays for the things such an addition entails in a C-like language. >The argument that alloca isn't a requirement because it's little-used >(and it's little-used because its not required) doesn't help much >either. It is rather circular, but the circle exists now and as a result it is hard to break out of it. In my opinion, when breaking such a circle it is best to do so cleanly, and (also my opinion) alloca is *not* clean. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
paulb@ssd.csd.harris.com (Paul Beusterien) (11/13/90)
In article <27608@mimsy.umd.edu> Chris Torek writes : > It is rather circular, but the circle exists now and as a result it is > hard to break out of it. In my opinion, when breaking such a circle it > is best to do so cleanly, and (also my opinion) alloca is *not* clean. In my opinion alloca is the cleanest way to allocate memory that is needed for the lifetime of a single routine. Why go to the trouble of allocating memory from a generic place when it can be associated with the routine that uses it? There can be major time and space gains by using alloca instead of malloc and free. It is obviously faster to adjust a stack pointer than to search an available list and free it back up. Also, space may be saved because of less fragmentation. If another routine has already alloca'ed space or there has been a lot of recursion in some other place in the program, the alloca may be completely free because the stack space has already been allocated. -- Paul Beusterien paulb@ssd.csd.harris.com Harris Computer Systems {uunet,mit-eddie,novavax}!hcx1!paulb Ft. Lauderdale, FL voice: (305) 973 5270
s64421@zeus.usq.EDU.AU (house ron) (11/13/90)
paulb@ssd.csd.harris.com (Paul Beusterien) writes: >In article <27608@mimsy.umd.edu> Chris Torek writes : >> It is rather circular, but the circle exists now and as a result it is >> hard to break out of it. In my opinion, when breaking such a circle it >> is best to do so cleanly, and (also my opinion) alloca is *not* clean. >In my opinion alloca is the cleanest way to allocate memory that is needed >for the lifetime of a single routine. Why go to the trouble of allocating >memory from a generic place when it can be associated with the routine >that uses it? >There can be major time and space gains by using alloca instead of malloc >and free. It is obviously faster to adjust a stack pointer than to search >an available list and free it back up. ABsolutely! It is a crying shame that alloca is not in ANSI. Of course the real culprit is the absence of declarations with variable bounds (int a[n]). Efficiency arguments about _that_ one really are rather pathetic, given that all sane computers nowadays have a good efficient stack. BTW, I have found that alloca can usually be programmed for most compilers, provided you promise yourself only to use it immediately on entry to a function which declares at least one variable. Optimisers are pretty hard put to foul that up. -- Regards, Ron House. (s64421@zeus.usq.edu.au) (By post: Info Tech, U.C.S.Q. Toowoomba. Australia. 4350)
chris@mimsy.umd.edu (Chris Torek) (11/13/90)
In article <27608@mimsy.umd.edu> I wrote: >>>... the circle exists now and as a result it is hard to break out of it. >>>In my opinion, when breaking such a circle it is best to do so cleanly, >>>and (also my opinion) alloca is *not* clean. In article <PAULB.90Nov12131357@hcx2.ssd.csd.harris.com> paulb@ssd.csd.harris.com (Paul Beusterien) writes: >>In my opinion alloca is the cleanest way to allocate memory that is needed >>for the lifetime of a single routine. ... [comparison with malloc deleted] I disagree; however, we may well be on the same side: >>There can be major time and space gains by using alloca instead of malloc >>and free. It is obviously faster to adjust a stack pointer than to search >>an available list and free it back up. There may be major correctness losses using alloca (as I wrote earlier, any optimizing compiler can easily produce failing object code from apparently-correct source code if that source code uses alloca). (For fun, try compiling #include <stdio.h> void g(p, n) char *p; int n; { printf("got %lx, %d\n", (long)p, n); } void f(n) int n; { char *p = alloca(n); g(p, n); } int main() { f(23); return 0; } and then the `optimized' version: #include <stdio.h> void g(p, n) char *p; int n; { printf("got %lx, %d\n", (long)p, n); } void f(n) int n; { g(alloca(n), n); } int main() { f(23); return 0; } on fifty different architectures or so, and count success to failure ratios. You may have to compile the first without any optimisation.) In article <s64421.658490039@zeus> s64421@zeus.usq.EDU.AU (house ron) writes: >ABsolutely! It is a crying shame that alloca is not in ANSI. Of >course the real culprit is the absence of declarations with variable >bounds (int a[n]). Exactly. Alloca is not the solution. Alloca is a dirty hack. The solution to the problem at hand---namely, allocating local space, as opposed to heap space, when the amount of space is not known at compile time---should be something directly in the language.% If you need `n' `struct xyzzy's, struct xyzzy *p = alloca(n * sizeof *p); is not the right answer, precisely because alloca is not known to the compiler even though the things the compiler does with the stack (if there is a stack; if not, all the arguments for local allocation fall apart anyway; you might as well use a more general scheme) affect its operation. The stack frames produced by optimising compilers are NOT easily predictable. ----- % Note, all of this continues to be prefixed with an invisible `in my opinion'. ----- Now, I personally remain uncertain as to whether gcc's approach is `good enough', or whether Dennis Ritchie's proposal for NCEG is `best', or whether simply declaring the name `alloca' to be a new keyword is the `best' answer. The main advantage that struct xyzzy p[n]; (where `n' is a variable) has over the alloca hack is that the former fails noisily whenever it fails, while the latter fails quietly when the compiler happens to disarrange the stack because that saves a few instructions. Alloca is, as Richard O'Keefe noted, a rather triangular wheel. There are rounder ones. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (11/14/90)
In article <s64421.658490039@zeus> s64421@zeus.usq.EDU.AU (house ron) writes: > given that all sane computers nowadays have a good > efficient stack. Oh? I regularly use a supermini (not a slow little Sun---this thing can run up to twice as fast as a Convex on non-vector codes) that doesn't have *any* stack. *None*. It also takes two instructions to load from memory. It also has separate integer and floating-point instruction streams, each dealing with thirty-two registers. As you can imagine, the compiler does a lot of work. As does the instruction scheduler. Do you have some religious objection to machines with simulated stacks, or do you have some rational reason that they're not ``sane''? ---Dan
dave@tygra.ddmi.com (David Conrad) (11/14/90)
In article <PAULB.90Nov12131357@hcx2.ssd.csd.harris.com> paulb@ssd.csd.harris.com (Paul Beusterien) writes:
)
)In my opinion alloca is the cleanest way to allocate memory that is needed
)for the lifetime of a single routine. Why go to the trouble of allocating
)memory from a generic place when it can be associated with the routine
)that uses it?
)
Okay, I'm ready to draw major flames here. This has already been added.
In C++ the destructor of a class is automatically called when a variable
of that class goes out of scope. The destructor can perform cleanup like
deallocating memory, etc.
I certainly hope I remembered my flame-retardant underwear.
--
David R. Conrad
dave@tygra.ddmi.com
Following inconveniently added by system:
--
= CAT-TALK Conferencing Network, Prototype Computer Conferencing System =
- 1-800-825-3069, 300/1200/2400/9600 baud, 8/N/1. New users use 'new' -
= as a login id. <<Redistribution to GEnie PROHIBITED!!!>>> =
E-MAIL Address: dave@ThunderCat.COM
chris@mimsy.umd.edu (Chris Torek) (11/15/90)
In article <27634@mimsy.umd.edu> I wrote: >... The main advantage that > struct xyzzy p[n]; >(where `n' is a variable) has over the alloca hack is that the former >fails noisily whenever it fails, while the latter fails quietly when >the compiler happens to disarrange the stack because that saves a few >instructions. Oops, `former' and `latter' are reversed above. I meant that the array declaration fails noisily, while the alloca call fails silently (for more evidence, see the posting from someone who had this happen on that most forgiving of machines, a VAX). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
djones@megatest.UUCP (Dave Jones) (11/16/90)
I don't see using alloca() as a high crime or a misdemeanor, but if you are afraid of being castaway on the Isle of Enemy Computers, where alloca() doesn't work right, you can use a hand-rolled memory allocation package based on a separate stack. That's handy anyway for applications whose data are naturally stackable (or "treeable"), but whose flow of control does not precisely follow the stacking and unstacking. It goes like this: The program obtains pointers into the stack ("stack-marks") and later can free all the memory allocated after the mark was obtained, all it one swell foop. Of course you will usually want the stack to be "virtual" in the sense that it is not really one contiguous section of memory, and it can grow without bound. #include "ut_Lifo.h" typedef struct { int block_size; /* size of stack-sections */ int bytes_left; /* number of bytes free top section */ Lifo free_blocks; /* list of free sections */ Lifo blocks; /* the stack per se. */ }Stack; typedef struct { char* block; /* section of the stack on top at time of mark */ int bytes_left; /* top byte within that section. */ }Stack_mark; The above implementation uses stack-sections all of one size, so the maximum possible request must be known. For the application it was designed for that is no problem. A little bit more overhead, and it could use sections of undetermined size, perhaps growing them by a multiple of 3/2 or 2 as more sections are required. But the one I'm using is built for speed, being approximately as fast as alloc() on the machines it runs on. A note on longjmp's: The purpose of a longjmp is quite similar to poping the memory-stack to a mark: It pops off a bunch of function- activations all at one go when they become unneeded, often because of an error-condition. The code that does the "real" setjmp should obtain the stack-mark and the code that gets longjmp'd to should pop the stack to that point: Stack stack; static Stack_mark stack_mark; static jmp_buf proc_mark; ... if(setjmp(proc_mark) == 0) { stack_mark = Stack_mark_get(&stack); } else { Stack_pop_to_mark(&stack, stack_mark); }
seanf@sco.COM (Sean Fagan) (11/16/90)
In article <PAULB.90Nov12131357@hcx2.ssd.csd.harris.com> paulb@ssd.csd.harris.com (Paul Beusterien) writes: >There can be major time and space gains by using alloca instead of malloc >and free. It is obviously faster to adjust a stack pointer than to search >an available list and free it back up. ``Stack pointer''? What is a ``stack pointer''? On some of my favorite machines, there is no concept of something called a ``stack.'' (Well, actually, the Cyber has a "stack," but its "stack" is actually a 10-word instruction queue.) I just tried a small program, and using alloca() caused a coredump. You know, I think you're right: that saved me *so* much time, space, and effort! I'm *so* glad I used it! (Note for the curious: if trying to generate code that will break, it is ofttimes helpful to know the compiler somewhat intimately 8-).) Lessee... we've had Chris and Doug denounce alloca(), but I haven't seen anything from Henry (yet? I suspect he would also denounce it). Dennis? -- -----------------+ Sean Eric Fagan | "*Never* knock on Death's door: ring the bell and seanf@sco.COM | run away! Death hates that!" uunet!sco!seanf | -- Dr. Mike Stratford (Matt Frewer, "Doctor, Doctor") (408) 458-1422 | Any opinions expressed are my own, not my employers'.
fjb@metaware.metaware.com (Fred Bourgeois) (11/17/90)
In article <27634@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes: >In article <PAULB.90Nov12131357@hcx2.ssd.csd.harris.com> >paulb@ssd.csd.harris.com (Paul Beusterien) writes: >>>In my opinion alloca is the cleanest way to allocate memory that is needed >>>for the lifetime of a single routine. ... [comparison with malloc deleted] >I disagree; however, we may well be on the same side: Clean or not clean, it is the fastest way to allocate memory needed only for the lifetime of the current routine. Assuming your compiler implements it properly. If you're not sure, use the `#define alloca malloc' method. >There may be major correctness losses using alloca (as I wrote earlier, >any optimizing compiler can easily produce failing object code from >apparently-correct source code if that source code uses alloca). >(For fun, try compiling [example deleted] >on fifty different architectures or so, and count success to failure >ratios. You may have to compile the first without any optimisation.) Oh come on! You can't claim this as a problem with alloca! The standard clearly states (Appendix F.1) that "the order in which side-effects take place" is unspecified. And clearly, alloca has a side effect - it modifies the (possibly virtual) stack pointer. Also consider 3.3.2.2, the order of evaluation of arguments to a function is unspecified. Try the following on fifty different architectures and see what results you get: #include <stdio.h> /* insert your favorite push/pop functions */ extern int push(int s); /* push returns argument pushed */ extern int pop(void); int main() { #if defined OPT printf("stack(%d %d)\n", push(23), pop()); #else int a = push(23); printf("stack(%d %d)\n", a, pop()); #endif } This is just another area in which the programmer must be aware of a subtlety in the language. >In article <s64421.658490039@zeus> s64421@zeus.usq.EDU.AU (house ron) writes: >>ABsolutely! It is a crying shame that alloca is not in ANSI. Of >>course the real culprit is the absence of declarations with variable >>bounds (int a[n]). > >Exactly. Alloca is not the solution. Alloca is a dirty hack. The >solution to the problem at hand---namely, allocating local space, as >opposed to heap space, when the amount of space is not known at compile >time---should be something directly in the language.% [stuff deleted] I agree, the standard should specify a method for allocating local space. Given good compiler support for alloca, and programmer awareness of the pitfalls (e.g. side-effects are not portable, etc.), alloca is an adequate solution *for the time being*. In my opinion, it should eventually be made a part of the standard, because it is also the fastest way to allocate local memory. --- Fred Bourgeois, MetaWare Inc., 2161 Delaware Avenue, Santa Cruz, CA 95060-2806 fjb@metaware.com ...!uunet!metaware!fjb Colorless Green Ideas Sleep Furiously, and so do I.
bright@nazgul.UUCP (Walter Bright) (11/17/90)
In article <27634@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
/There may be major correctness losses using alloca (as I wrote earlier,
/any optimizing compiler can easily produce failing object code from
/apparently-correct source code if that source code uses alloca).
You're right. I struggled with this problem for a while, until the
solution became obvious: make alloca() a 'magic' function, and have
the optimizations take it into account. I implemented this, and it
works fine (including in those cases you pointed out, and the cases
in the MSC manual where it says not to use it).
ANSI C allows other functions to be magic.
But the fact remains that if you wish to write maximally portable programs
you are better off avoiding alloca.
henry@zoo.toronto.edu (Henry Spencer) (11/18/90)
In article <8789@scolex.sco.COM> seanf@sco.COM (Sean Fagan) writes: >Lessee... we've had Chris and Doug denounce alloca(), but I haven't seen >anything from Henry (yet? I suspect he would also denounce it)... Suspicion confirmed. Alloca() is a kludge that should have died long ago. There *is* a general problem with the need for various kinds of cleanup on exiting a function, either by the normal route or by longjmp(), but alloca solves only one special case of that, at the cost of major portability problems and new opportunities for interesting bugs. A proper fix is impossible without language changes. -- "I don't *want* to be normal!" | Henry Spencer at U of Toronto Zoology "Not to worry." | henry@zoo.toronto.edu utzoo!henry
chris@mimsy.umd.edu (Chris Torek) (11/20/90)
In article <27634@mimsy.umd.edu> I wrote: >>There may be major correctness losses using alloca (as I wrote earlier, >>any optimizing compiler can easily produce failing object code from >>apparently-correct source code if that source code uses alloca). [example deleted] In article <656@metaware.metaware.com> fjb@metaware.metaware.com (Fred Bourgeois) writes: >Oh come on! You can't claim this as a problem with alloca! The standard >clearly states (Appendix F.1) that "the order in which side-effects take >place" is unspecified. And clearly, alloca has a side effect - it modifies >the (possibly virtual) stack pointer. Also consider 3.3.2.2, the order of >evaluation of arguments to a function is unspecified. [different example deleted] >This is just another area in which the programmer must be aware of a subtlety >in the language. But this is just the point---alloca is NOT IN THE LANGUAGE! You say that alloca `modifies the ... stack pointer'. Not only might there be no stack *pointer*, but there may even be no *stack*. My example was a transformation of the form unaliased_local_var_1 = function_1(); function_2(unaliased_local_var_1, unaliased_local_var_2); becomes function_2(function_1(), unaliased_local_var_2); By translating the ANSI C standard into formal specifications, I claim I can prove that this transformation is correct. And it *is* correct, for every correctly-implemented function *except* alloca(). (It can fail on improperly implemented functions, e.g., if function_1 were char *foo(int n) { char buf[20]; (void) sprintf(buf, "%d", n); return buf; } then this particular transformation might cause different local memory allocation patterns and cause the returned buffer to be overwritten earlier). Anyway, we have seen testimony from various people (including the author of the Zortech C compiler) that it is not possible to optimize correctly when `alloca' is used, unless you have the source to the compiler. >I agree, the standard should specify a method for allocating local space. >Given good compiler support for alloca, and programmer awareness of the >pitfalls (e.g. side-effects are not portable, etc.), alloca is an adequate >solution *for the time being*. In my opinion, it should eventually be made >a part of the standard, because it is also the fastest way to allocate local >memory. This is a different argument: `we need this functionality, and we think this is the right way to provide it', as opposed to `this is the way to do it'. If you want to argue for alloca support in compilers, and want people to use alloca (at the risk of having their code fail, apparently at random, when they use compilers without such support), that is fine with me---as long as you warn them. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (11/21/90)
...allocating local space, as opposed to heap space, when the amount of space is not known at compile time---should be something directly in the language. Hmmm...this borders on a false dichotomy. Since this assumption of alloca() space vs heap space is implicit in many of the postings I have seen, let's take a look. On the one hand, you have stack vs heap, i.e., you're talking about physical arrangement of memory. On the other hand, you have (at run-time) local scope vs global scope, i.e., you're talking about the lifetime of objects. The two are related but not mutually exclusive. Why does a built-in alloca() have to allocate space on the stack (or on any stack)? (Let's ignore memory models and Intel CPUs for a moment.) The requirements for alloca() are: (a) it allocates space when invoked, and (b) when the current run-time scope is exited, the allocated space is recovered for future use. If Doug Gwyn's nearly-portable alloca() can use heap space, why shouldn't a compiler built-in be able to do the same even more effectively? The key thing that needs to be done is to make sure that all possible ways of exiting the current scope go through the same place. Then, at that place in the code, you can manually deallocate all storage that was allocated by using alloca() (or malloc()). Since the compiler can more easily arrange for all scope exists to trigger the execution of the deallocation code, alloca() should be a built-in. OR some other feature of the language, like atexit() but possibly called atreturn(), should trigger the execution of user-specified code at scope exit. An atreturn() mechanism will lead to confusing and error-prone code, however, which is why alloca() should be built-in. -- Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com> UUCP: oliveb!cirrusl!dhesi
djones@megatest.UUCP (Dave Jones) (11/22/90)
From article <1990Nov17.221822.25202@zoo.toronto.edu>, by henry@zoo.toronto.edu (Henry Spencer): > A proper fix is > impossible without language changes. Isn't the change simply to legitimize alloca(), letting the compiler in on the gag? That's what Sun did.
henry@zoo.toronto.edu (Henry Spencer) (11/24/90)
In article <14517@megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes: >> A proper fix is >> impossible without language changes. > >Isn't the change simply to legitimize alloca(), letting the compiler >in on the gag? That's what Sun did. Please *read* the article you are responding to! Memory allocation is only one small fragment of the general problem of cleanup-on-return, and often not the most important one. I was addressing the general problem. -- "I'm not sure it's possible | Henry Spencer at U of Toronto Zoology to explain how X works." | henry@zoo.toronto.edu utzoo!henry
djones@megatest.UUCP (Dave Jones) (11/29/90)
From article <1990Nov24.035618.11358@zoo.toronto.edu>, by henry@zoo.toronto.edu (Henry Spencer): > In article <14517@megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes: >>> A proper fix is >>> impossible without language changes. >> >>Isn't the change simply to legitimize alloca(), letting the compiler >>in on the gag? That's what Sun did. > > Please *read* the article you are responding to! Memory allocation is only > one small fragment of the general problem of cleanup-on-return, and often not > the most important one. I was addressing the general problem. > -- > "I'm not sure it's possible | Henry Spencer at U of Toronto Zoology > to explain how X works." | henry@zoo.toronto.edu utzoo!henry
torek@elf.ee.lbl.gov (Chris Torek) (03/03/91)
In article <51339@cornell.UUCP> ressler@cs.cornell.edu (Gene Ressler) writes: >I'm asking those who are really familiar with the TC's code generator >if they know of other dangers e.g. functions with no locals, >tail calls, nested blocks with locals, and so on. ... This sort of thing is exactly why (choose all that apply): (a) alloca should never be used; (b) alloca must be built into the compiler; (c) using alloca makes code less portable. (Note that different people will choose different sets.) -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov