[comp.lang.c] alloca

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