[comp.lang.c] scope of malloc

mferrare@adelphi.ua.oz.au (Mark Ferraretto) (11/07/90)

You see, I have this question...
	When malloc is called in a function and the scope of the pointer is
only that function is the memory deallocated when the pointer is (ie on exit
of the function?) deallocated?  Or does that chunk of memory hang around util
the program terminates?  I am calling several functions that involve a lot of
dynamic memory allocation most of which is only relevant to the scope of the
function where the memory is allocated.  These functions get called repeatedly.
So do I need to fill these functions to include free() calls with at the end
of each function?
	System:   SunOS 4.0.3, NewsOS
	compiler: cc (came with os in all cases)
	machines: sun4/280 sun3/60, News1580, News3410 (coming soon)
Thanks for your help.
Please e-mail to me as I don't usually read this newsgroup.
Mark Ferraretto
mferrare@physics.adelaide.edu.au
       _             Name  : Mark Ferraretto
      \  \           Place : Department of Physics and Mathematical Physics
 ||     \  \                 University of Adelaide
==========>==>==--   Aarnet: mferrare@physics.adelaide.edu.au

gwyn@smoke.brl.mil (Doug Gwyn) (11/07/90)

In article <1791@sirius.ucs.adelaide.edu.au> mferrare@adelphi.ua.oz.au (Mark Ferraretto) writes:
>	When malloc is called in a function and the scope of the pointer is
>only that function is the memory deallocated when the pointer is (ie on exit
>of the function?) deallocated?  Or does that chunk of memory hang around util
>the program terminates?

The storage remains allocated until explicitly free()d or the program
terminates, whichever occurs first.  It would be truly horrible if the
storage were deallocated based on dynamic scoping as you suggest; that
would make it very hard to construct elaborate data structures, since
you'd have to do all the allocation within the same function that uses
the structure.

>I am calling several functions that involve a lot of
>dynamic memory allocation most of which is only relevant to the scope of the
>function where the memory is allocated.  These functions get called repeatedly.
>So do I need to fill these functions to include free() calls with at the end
>of each function?

Yes, or if you can simply declare them as auto variables they'll be cleaned
up for you.

>Please e-mail to me as I don't usually read this newsgroup.

Too bad.

cpcahil@virtech.uucp (Conor P. Cahill) (11/07/90)

In article <1791@sirius.ucs.adelaide.edu.au> mferrare@adelphi.ua.oz.au (Mark Ferraretto) writes:
>	When malloc is called in a function and the scope of the pointer is
>only that function is the memory deallocated when the pointer is (ie on exit
>of the function?) deallocated?

The data area pointed to by the value returned by malloc is allocated and
available until you free it or the program exits.

>I am calling several functions that involve a lot of
>dynamic memory allocation most of which is only relevant to the scope of the
>function where the memory is allocated.  These functions get called repeatedly.
>So do I need to fill these functions to include free() calls with at the end
>of each function?

Instead you could do something like:

	func() {
		static char *  pointer = NULL;

		if( pointer == NULL )
			pointer = malloc()...

If the pointer changes size:

		if( pointer == NULL )
			pointer = malloc(...
		else if ( new_size > old_size )
			pointer = realloc(...

If you just want the pointer to be around during the function, you can
use alloca() which allocates the data on your stack.  This function is 
usually hidden in the libPWB.a library.

-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.,
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

scs@adam.mit.edu (Steve Summit) (11/08/90)

In article <1990Nov07.134942.7355@virtech.uucp> cpcahil@virtech.UUCP (Conor P. Cahill) writes:
>If you just want the pointer to be around during the function, you can
>use alloca() which allocates the data on your stack.

Correction: "If you just want the pointer to be around during the
function and you want the program to be unportable...", as Doug
has just reminded us.

>This function is 
>usually hidden in the libPWB.a library.

...except under BSD, where it's right there in libc.a, and under
many other systems, where it doesn't exist at all.

The FAQ contains a bit more information on alloca.  The summary,
which bears repeating, stands: "alloca cannot be used in programs
which must be widely portable, no matter how useful it might be."

                                            Steve Summit
                                            scs@adam.mit.edu

rmartin@clear.com (Bob Martin) (11/09/90)

In article <1791@sirius.ucs.adelaide.edu.au> mferrare@adelphi.ua.oz.au (Mark Ferraretto) writes:
>You see, I have this question...
>	When malloc is called in a function and the scope of the pointer is
>only that function is the memory deallocated when the pointer is 
>(ie on exit of the function?) deallocated?  

The "scope" of memory allocated by malloc is the same as the scope
of a static variable.  The memory lasts until one of two events:
	1) you explicitly de-allocate it with the 'free' function.
	2) The program (main) exits or aborts.

It is possible to allocate memory which DOES get deallocated when
the allocating function returns.  You must use the function 'alloca'
which allocates the memory on the stack.  However use of this function
may not be portable.

-- 
+-Robert C. Martin-----+---------------------------------------------+
| rmartin@clear.com    | My opinions are mine.  They aren't anybody  |
| uunet!clrcom!rmartin | elses.  And thats the way I want to keep it.|
+----------------------+---------------------------------------------+

richard@aiai.ed.ac.uk (Richard Tobin) (11/10/90)

In article <1990Nov7.234315.15508@athena.mit.edu> scs@adam.mit.edu (Steve Summit) writes:
 [alloca]

>Correction: "If you just want the pointer to be around during the
>function and you want the program to be unportable..."

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.

-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

gwyn@smoke.brl.mil (Doug Gwyn) (11/10/90)

In article <3729@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>You have the choice of rejecting machines or compilers with such serious
>deficiencies as making alloca() impossible.

What nonsense.  Being unlike a VAX is hardly a "serious deficiency".

net@opal.cs.tu-berlin.de (Oliver Laumann) (11/11/90)

In article <14413@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
> In article <3729@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
> >You have the choice of rejecting machines or compilers with such serious
> >deficiencies as making alloca() impossible.
> 
> What nonsense.  Being unlike a VAX is hardly a "serious deficiency".

I'm not aware of any plausible reason why vendors should omit something
as useful and simple to implement as alloca() from their UNIX systems.

Yes, I know that alloca() may not work with certain existing C
compilers, but why, for instance, can't vendors with such types of
compilers add an option to support alloca() (like, e.g. Greenhills have
done with their C compiler) or implement alloca() as a built-in function
(like the SunOS cc does)?

You also keep mentioning the argument that alloca() is not needed.  If
this is true, then how do you make sure that in the following function,
which invokes another function that is supplied by user, the memory is
freed in case the user-supplied function doesn't return (i.e. invokes
longjmp())? --

   void wrapper (callback) void (*callback)(); {
       char *p;
       ...
       p = malloc (...);
       /* do something, then call user-supplied function */
       callback ();
       /* do something */
       free (p);
   }

Note that the implementor [implementer?] of the function "wrapper" has
no control over what "callback" does; "callback" is supplied by the
module's user.

Yes, I know that there do exist methods to solve problems like this
without using alloca() (I myself had to invent one for Elk, which
makes heavy use of alloca()), but a what price?

--
    Oliver Laumann, Technical University of Berlin, Germany.
    pyramid!tub!net   net@TUB.BITNET   net@tub.cs.tu-berlin.de

gwyn@smoke.brl.mil (Doug Gwyn) (11/12/90)

In article <2182@kraftbus.opal.cs.tu-berlin.de> net@tubopal.UUCP (Oliver Laumann) writes:
>Yes, I know that alloca() may not work with certain existing C
>compilers, but why, for instance, can't vendors with such types of
>compilers add an option to support alloca()

It's not simply a compiler issue; many interesting computer achitectures
are such that alloca() cannot be reasonably implemented, particularly if
you take into account interrupts (signals).

>You also keep mentioning the argument that alloca() is not needed.  If
>this is true, then how do you make sure that in the following function, ...

I don't write spaghetti code.

richard@aiai.ed.ac.uk (Richard Tobin) (11/13/90)

In article <14413@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:

>>You have the choice of rejecting machines or compilers with such serious
>>deficiencies as making alloca() impossible.

>What nonsense.  Being unlike a VAX is hardly a "serious deficiency".

As you know, there are plenty of machines that are quite unlike vaxes
that implement alloca().  I think you would even agree that there are
very few machines on which it is impossible.  So I think your comment
is pointless.

To return to the technical point, it is certainly true that it's hard
to implement alloca() efficiently *as a normal function* on several
processors.  An increasing number of compilers recognise alloca() as a
special case (typically #defining it as __builtin_alloca).  Sun's C
compiler and gcc are examples.  Are there *any* widely-used processors
that can't implement alloca() reasonably efficiently even with
compiler support?

-- Richard

-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (11/13/90)

In article <3739@skye.ed.ac.uk>, richard@aiai.ed.ac.uk (Richard Tobin) writes:
> Are there *any* widely-used processors
> that can't implement alloca() reasonably efficiently even with
> compiler support?

Any processor that can't implement alloca() as a built-in operation is
going to have a hard time with PL/I, Fortran 90, and Ada, all of which
allow the declaration of local variables whose size is not known until
the declaration is elaborated.  The fact that gcc supports alloca() as
well as "auto int foo[some_expr()]" is not a coincidence.

There is, by the way, a compromise position, which was provided in BCPL.
BCPL didn't have alloca(), but it did have 

	APTOVEC(function, size_of_memory_block)		// argument order?

The equivalent in C could almost be implemented as

	int aptovec(int (*fn)(void *), size_t amount)
	    {
		void *space = malloc(amount);
		int result = space ? fn(space) : -1;
		free(space);
		return result;
	    }

except that the memory is supposed to go away automatically on longjmp
as well as exit.  On the machines I know where alloca() is hard to do
as a normal function, aptovec() can be done quite easily in assembly code
with no special compiler support.  (Which is not to assert that this is
true on _all_ machines.  I don't _know_ all machines.)

The problem with people re-inventing the wheel (aptovec) is that
they tend to invent triangular ones (alloca).

-- 
The problem about real life is that moving one's knight to QB3
may always be replied to with a lob across the net.  --Alasdair Macintyre.

gwyn@smoke.brl.mil (Doug Gwyn) (11/13/90)

In article <3739@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>Are there *any* widely-used processors that can't implement alloca()
>reasonably efficiently even with compiler support?

It can't be implemented correctly (except by the compiler turning it into
malloc()/free() calls that you could have coded yourself) on any system
that doesn't provide separate frame and stack pointers.  Just consider
the effects of an interrupt.  It also cannot be reasonably implemented on
a system that uses linked stack frames, such as on the IBM System/370.

rjc@uk.ac.ed.cstr (Richard Caley) (11/13/90)

In article <14437@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:

    It's not simply a compiler issue; many interesting computer achitectures
    are such that alloca() cannot be reasonably implemented, particularly if
    you take into account interrupts (signals).

    In article <2182@kraftbus.opal.cs.tu-berlin.de> net@tubopal.UUCP (Oliver Laumann) writes:
    >You also keep mentioning the argument that alloca() is not needed.  If
    >this is true, then how do you make sure that in the following
    >function, [ simple callback scheme... ]

    I don't write spaghetti code.

My someone got out of bed the wrong side one Monday morning :-)

The code that was shown was not particularly opaque and was certainly
not unusual, it is the kind of thing that anyone putting together
generally useful support routines is going to have to do. 

As you point out, the same thing happens with interrupts.

Also, to tie in another thread, since one can't do line at a time
input without dynamically alocating memory, are we to assume that any
code of mine which is to be included in a larger system beyond my
control may not do line at a time input? Or are we all to live in
programmer heaven where all systems are one man jobs and are not
modified once completed?

--
rjc@uk.ac.ed.cstr

conor@lion.inmos.co.uk (Conor O'Neill) (11/13/90)

In article <2182@kraftbus.opal.cs.tu-berlin.de> net@tubopal.UUCP (Oliver Laumann) writes:
>I'm not aware of any plausible reason why vendors should omit something
>as useful and simple to implement as alloca() from their UNIX systems.
>
>Yes, I know that alloca() may not work with certain existing C
>compilers, but why, for instance, can't vendors with such types of
>compilers add an option to support alloca() (like, e.g. Greenhills have
>done with their C compiler) or implement alloca() as a built-in function
>(like the SunOS cc does)?

On some machines you require a different calling sequence if you want
to be able to implement alloca than would be required if you do not
need to implement alloca. (This is due to the requirement for
both a stack pointer and a frame pointer).
The different calling sequences may have different costs.

Some customers would prefer a faster C system _without_ alloca than
a slower C system _with_ alloca.

---
Conor O'Neill, Software Group, INMOS Ltd., UK.
UK: conor@inmos.co.uk		US: conor@inmos.com
"It's state-of-the-art" "But it doesn't work!" "That is the state-of-the-art".

richard@aiai.ed.ac.uk (Richard Tobin) (11/14/90)

In article <4251@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
>Any processor that can't implement alloca() as a built-in operation is
>going to have a hard time with PL/I, Fortran 90, and Ada, all of which
>allow the declaration of local variables whose size is not known until
>the declaration is elaborated.  The fact that gcc supports alloca() as
>well as "auto int foo[some_expr()]" is not a coincidence.

alloca() is in fact somewhat more powerful than variable-size locals,
since you can do an alloca() anywhere, rather than just at the start
of a function - even inside a loop.  [Of course, if the variable size
of your autos is determined by an arbitrary expression then "not just
at the start of a function" means little.]

Does this cause additional implementation problems on any
architectures?

-- Richard

-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

henry@zoo.toronto.edu (Henry Spencer) (11/14/90)

In article <2182@kraftbus.opal.cs.tu-berlin.de> net@tubopal.UUCP (Oliver Laumann) writes:
>You also keep mentioning the argument that alloca() is not needed.  If
>this is true, then how do you make sure that in the following function,
>which invokes another function that is supplied by user, the memory is
>freed in case the user-supplied function doesn't return (i.e. invokes
>longjmp())? --

How do you make sure that you get control back to perform other forms
of cleanup, e.g. buffer flushing?  The answer is, you tell the user
"the function you supply must return normally, not by longjmp()".
-- 
"I don't *want* to be normal!"         | Henry Spencer at U of Toronto Zoology
"Not to worry."                        |  henry@zoo.toronto.edu   utzoo!henry

jimp@cognos.UUCP (Jim Patterson) (11/14/90)

In article <3739@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>In article <14413@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>
>>>You have the choice of rejecting machines or compilers with such serious
>>>deficiencies as making alloca() impossible.
>
>>What nonsense.  Being unlike a VAX is hardly a "serious deficiency".
>
>As you know, there are plenty of machines that are quite unlike vaxes
>that implement alloca().  I think you would even agree that there are
>very few machines on which it is impossible.  So I think your comment
>is pointless.

Even alloca() on a VAX can be trouble, as I found out from direct
experience. When we first moved our products onto VAX/VMS using VAX-11
C (yes, VAX/VMS, not Ultrix or something else), we used a variant of
alloca() written in assembler (not too hard to do).  However, we found
that when we compiled our products with the /OPTIMIZE switch they
broke.  It turns out that VAX-11 C likes to address one or two words
off of the stack pointer SP since this generates shorter instructions
than frame-pointer-relative instructions for those particular
variables. By moving the stack pointer (what any typical alloca
implementation does), and not telling the compiler about it, we broke
the code.

Since /OPTIMIZE was more important for us than occasional increased
code efficiency using alloca(), we stopped using alloca(). We haven't
regretted it.

This could be fixed by a compiler-builtin, as Sun has done. We weren't
able to do this though since we don't have (and don't care to have)
the source to VAX-11 C.
-- 
Jim Patterson                              Cognos Incorporated
UUCP:uunet!mitel!cunews!cognos!jimp        P.O. BOX 9707    
PHONE:(613)738-1440                        3755 Riverside Drive
NOT a Jays fan (not even a fan)            Ottawa, Ont  K1G 3Z4

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (11/14/90)

In article <14448@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes:
: In article <3739@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
: >Are there *any* widely-used processors that can't implement alloca()
: >reasonably efficiently even with compiler support?

: It can't be implemented correctly (except by the compiler turning it into
: malloc()/free() calls that you could have coded yourself) on any system
: that doesn't provide separate frame and stack pointers.  Just consider
: the effects of an interrupt.  It also cannot be reasonably implemented on
: a system that uses linked stack frames, such as on the IBM System/370.

Surely the significant part of Richard Tobin's posting was the
magic phrase EVEN WITH COMPILER SUPPORT?

Algol 60 compilers, Algol 68 compilers (_love_ that Algol 68C), Simula 67
compilers, PL/I Fortran 90 compilers, Ada compilers, *all* have to be able
to do what is required.

One method:
    have an "aptovec stack" as well as the procedure call stack,
    dedicate two slots in the frame of a function IF that function
    calls alloca().
	function entry:
		alloca_frame_link = global_alloca_link;
		global_alloa_link = &alloca_frame_link;
		alloca_frame_save = alloca_stack_top;
	function exit:
		alloca_stack_top = alloca_frame_save;
	call x = alloca(n)
		alloca_stack_top = n + (x = alloca_stack_top);
    longjmp() unwinds the linked list of frames, resetting alloca_stack_top
    as it goes.

If it is possible to set aside an area of VM for this, that's all you need.
If you need to allocate the "aptovec stack" in chunks, it gets a bit harder,
but not much.

This message should not be taken as endorsing the alloca() interface as such.
-- 
The problem about real life is that moving one's knight to QB3
may always be replied to with a lob across the net.  --Alasdair Macintyre.

fjb@metaware.metaware.com (Fred Bourgeois) (11/14/90)

In article <14448@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <3739@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>>Are there *any* widely-used processors that can't implement alloca()
>>reasonably efficiently even with compiler support?
>
>It can't be implemented correctly (except by the compiler turning it into
>malloc()/free() calls that you could have coded yourself) on any system
>that doesn't provide separate frame and stack pointers.  Just consider
>the effects of an interrupt.  It also cannot be reasonably implemented on
>a system that uses linked stack frames, such as on the IBM System/370.

You are Wrong.

Our compiler implements alloca() as an intrinsic, and does it correctly.

... even on the 370 ...

------------------------------------------------------------------------------
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.
------------------------------------------------------------------------------

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (11/14/90)

In <2182@kraftbus.opal.cs.tu-berlin.de> net@opal.cs.tu-berlin.de
(Oliver Laumann) writes:

>I'm not aware of any plausible reason why vendors should omit something
>as useful and simple to implement as alloca() from their UNIX systems.

I too am not aware of one.

The designers of Ada assumed that such functionality would be available
in the language, and this is why they didn't worry too much about
requiring the equivalent of a free() function in the language.  (Well,
actually, they did worry about it, but in the reverse manner, arguing
that the availability of an unchecked way of freeing allocated memory
was dangerous, and it had better be indicated so in bold letters that
read something like UNCHECKED_DEALLOCATION.  Their preference was for
the memory allocated for objects in the heap to be freed automatically
when the scope of the objects expired at run-time, i.e., through a
mechanism equivalent to alloca().)

I think the problem, to quote Chris Torek somewhat out-of-context, is
that you're in a circle and it's hard to break out of it.  Since
alloca() must properly be designed into the compiler, it's hard to find
"prior art" in the form of user-written functions.  Since programmers
can't always assume the availability of alloca(), they find ways around
it -- and I suspect some of them, having worked hard to find ways
around it, aren't sympathetic to others who don't want to work so
hard.

I'm sure there are some very-CISC machine architectures in which
procedure exit is a single instruction, and adding alloca() would
result in less efficient procedure exit code that couldn't use this
single instruction.  But I don't see why alloca() should be impossible,
or even difficult, to implement on any machine.  Heck, if you can
implement a recursive language on a machine that doesn't have a stack
to begin with (e.g. IBM 360 onwards), and not complain about how
"impossible" it is to write a PL/1 compiler, you can surely implement
alloca() on every machine in the world.

There's enough prior art now, though, that perhaps the next team that
revises the C standard may be persuaded to add alloca() to it.
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

richard@aiai.ed.ac.uk (Richard Tobin) (11/14/90)

In article <14448@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>It can't be implemented correctly (except by the compiler turning it into
>malloc()/free() calls that you could have coded yourself) on any system
>that doesn't provide separate frame and stack pointers.  Just consider
>the effects of an interrupt.

I assume you mean a system that accesses locals by offsets from the stack 
pointer, implements alloca() by using space beyond the stack pointer,
and receives interrupts on the same stack.  This indeed cannot work.

However, the frame pointer doesn't have to be a dedicated register.
The compiler can just allocate a register for local references in
functions that call alloca().  (I assume that compilers like gcc which
have an option to not use a frame pointer have the same problem, and
disable this option in functions that call alloca()).

And of course if the compiler can turn it into malloc()/free() calls
*and ensure the free() gets done when a longjmp() occurs (which the
user can't)*, then this would be a reasonable implementation.

>It also cannot be reasonably implemented on
>a system that uses linked stack frames, such as on the IBM System/370.

This might be a problem, but as Richard O'Keefe has pointed out, they
would have to solve it to implement various other languages.  A
solution in C (which only has local and global variables, and wouldn't
therefore have to follow the frame chain) might be to implement
alloca() by inserting a frame in the chain.

-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

richard@aiai.ed.ac.uk (Richard Tobin) (11/14/90)

In article <12559@ganymede.inmos.co.uk> conor@inmos.co.uk (Conor O'Neill) writes:
>Some customers would prefer a faster C system _without_ alloca than
>a slower C system _with_ alloca.

They'd both be happy if the system were only slower when you actually
used alloca().  This may be possible on a function-by-function basis.

-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

gwyn@smoke.brl.mil (Doug Gwyn) (11/14/90)

In article <650@metaware.metaware.com> fjb@metaware.UUCP (Fred Bourgeois) writes:
>Our compiler implements alloca() as an intrinsic, and does it correctly.
>... even on the 370 ...

The argument in X3J11 was that in some environments you'd have to pay a
speed penalty in non-alloca() code in order to have full support for alloca(),
a trade-off that few implementors would be willing to make (considering that
the vast majority of commercially important C code makes no use whatever of
alloca()).

net@opal.cs.tu-berlin.de (Oliver Laumann) (11/16/90)

In article <14437@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
> In article <2182@kraftbus.opal.cs.tu-berlin.de> net@tubopal.UUCP (Oliver Laumann) writes:
> >You also keep mentioning the argument that alloca() is not needed.  If
> >this is true, then how do you make sure that in the following function, ...
> 
> I don't write spaghetti code.

I'm not sure I understand this remark.  According to the computer jargon
dictionary, spaghetti code is defined as follows:

SPAGHETTI CODE (sp@-get'ee kohd) n. Describes code with a complex and
   tangled control structure, esp. one using many GOTOs, exceptions or
   other `unstructured' branching constructs. Pejorative.

In what way did the program fragment in my article qualify as spaghetti
code?  Do you regard "callback functions" as a tangled control structure
or an unstructured branching construct (in this case you must really
hate X11 :-)

--
Oliver Laumann     net@TUB.BITNET     net@tub.cs.tu-berlin.de     net@tub.UUCP

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (11/17/90)

In article <2229@kraftbus.opal.cs.tu-berlin.de> net@tubopal.UUCP (Oliver Laumann) writes:
> In what way did the program fragment in my article qualify as spaghetti
> code?  Do you regard "callback functions" as a tangled control structure
> or an unstructured branching construct (in this case you must really
> hate X11 :-)

As callback functions and object-oriented programming are essentially
equivalent, I'd be amused to see the former declared ``unstructured.''

---Dan

gwyn@smoke.brl.mil (Doug Gwyn) (11/17/90)

In article <2229@kraftbus.opal.cs.tu-berlin.de> net@tubopal.UUCP (Oliver Laumann) writes:
>> I don't write spaghetti code.
>I'm not sure I understand this remark.  According to the computer jargon
>dictionary, spaghetti code is defined as follows: ...

Yes, exactly.  You might also look up the definition for structured code
to see the contrast.

ark@alice.att.com (Andrew Koenig) (11/18/90)

In article <4251@goanna.cs.rmit.oz.au> ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
> In article <3739@skye.ed.ac.uk>, richard@aiai.ed.ac.uk (Richard Tobin) writes:
> > Are there *any* widely-used processors
> > that can't implement alloca() reasonably efficiently even with
> > compiler support?

> Any processor that can't implement alloca() as a built-in operation is
> going to have a hard time with PL/I, Fortran 90, and Ada, all of which
> allow the declaration of local variables whose size is not known until
> the declaration is elaborated.  The fact that gcc supports alloca() as
> well as "auto int foo[some_expr()]" is not a coincidence.

Quite true -- most C compilers will have a hard time compiling PL/I or Ada!

Seriously, though, if one decides to make it impossible to support
alloca(), as the definition of ANSI C allows, it is sometimes possible
to produce significantly faster object code as a result.

For example, barring alloca() means that the compiler can always know
the size of the stack frame.  That, in turn, means that it is possible
to maintain the stack using only a single pointer.  That implies that
a function call need update only one stack register and not two.

-- 
				--Andrew Koenig
				  ark@europa.att.com

paulb@ssd.csd.harris.com (Paul Beusterien) (11/20/90)

In article <11631@alice.att.com> (Andrew Koenig) writes :
> Seriously, though, if one decides to make it impossible to support
> alloca(), as the definition of ANSI C allows, it is sometimes possible
> to produce significantly faster object code as a result.
> 
> For example, barring alloca() means that the compiler can always know
> the size of the stack frame.  That, in turn, means that it is possible
> to maintain the stack using only a single pointer.  That implies that
> a function call need update only one stack register and not two.

Not necessarily.  It may be possible to use one stack pointer all the
time except for routines that use alloca.  In the routines that call
alloca, the performance gains of alloca more than make up for the
overhead of using a second stack pointer for the frame.
--
Paul Beusterien                          paulb@ssd.csd.harris.com
Harris Computer Systems        {uunet,mit-eddie,novavax}!hcx1!paulb
Ft. Lauderdale, FL                     voice: (305) 973 5270

bright@nazgul.UUCP (Walter Bright) (11/20/90)

/I guess with a little help from a god, writing a whole compiler to handle
/one routine can be considered "reasonable," but most of us don't necessarily
/think so (this coming from someone who worked on compilers for quite a
/while).

I write compilers for a living (Zortech's). I implemented alloca() as a
compiler intrinsic in a few hours, including a test suite for it. Mostly
it consisted of setting a flag telling the code generator to always do
a full stack frame for that function.

Most people tell me I'm conceited, but I didn't think that implementation
of alloca() was that godlike! :-) I always think of setting flags that
perturb the code generator as a kludge to be avoided.

Maybe it was that Coca-Cola induced euphoria :-)

scjones@thor.UUCP (Larry Jones) (11/21/90)

In article <2229@kraftbus.opal.cs.tu-berlin.de>, net@opal.cs.tu-berlin.de (Oliver Laumann) writes:
> In what way did the program fragment in my article qualify as spaghetti
> code?  Do you regard "callback functions" as a tangled control structure
> or an unstructured branching construct (in this case you must really
> hate X11 :-)

I don't know about Doug, but *I* sure reguard callbacks as both tangled
control structures and unstructured braches.  In fact, they seem to be
very closely related to the "altered goto" which seem to be held in more
or less universal contempt.  Mind you, I'm not saying they aren't USEFUL,
just that they're very hard to follow!  
----
Larry Jones                         UUCP: uunet!sdrc!thor!scjones
SDRC                                      scjones@thor.UUCP
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
Archaeologists have the most mind-numbing job on the planet. -- Calvin

djones@megatest.UUCP (Dave Jones) (11/22/90)

From article <11631@alice.att.com>, by ark@alice.att.com (Andrew Koenig):
...
> For example, barring alloca() means that the compiler can always know
> the size of the stack frame.  That, in turn, means that it is possible
> to maintain the stack using only a single pointer.  That implies that
> a function call need update only one stack register and not two.

The Sun C compiler does alloca() properly, so far as I know, so it does
not "know" the size of the stack frame at compile-time. Yet,
not only does it maintain the stack using a single pointer, and
the function call only updates one stack register, but if you don't call
alloca(), the stack pointer is doesn't change until the procedure returns!
It's all kind of clever the way it works. See the SPARC Architecture
Manual, pg. 160.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (11/22/90)

In article <11631@alice.att.com>, ark@alice.att.com (Andrew Koenig) writes:
: Seriously, though, if one decides to make it impossible to support
: alloca(), as the definition of ANSI C allows, it is sometimes possible
: to produce significantly faster object code as a result.

We are still waiting to be told about any machine on which this is true.

: For example, barring alloca() means that the compiler can always know
: the size of the stack frame.  That, in turn, means that it is possible
: to maintain the stack using only a single pointer.  That implies that
: a function call need update only one stack register and not two.

This is just sloppy thinking.  It has been pointed out several times
that the compiler can always know the size of the stack frame for any
function in which alloca() does not actually occur.  Indeed, whoever
said alloca() had to allocate memory from the current stack frame?
The argument "alloca() means you have to use more than one stack register"
is completely false.  The significant point about alloca() is that the
space goes away when you exit the function, whether by normal return or
by longjmp().  There is no promise, for example, that memory allocated by
two successive calls to alloca() is contiguous.  (The natural implementation
of alloca() on a Prime 400, for example, using the P400's stack extension
instruction, would yield no such guaranteee.)  I sketched an implementation
of alloca(), based on traditional Algol techniques, in which *every* function
could use the one-register frame-size-always-known protocol whether alloca()
was used or not.

The following statement appears to be true:
    with a small amount of compiler support,
    and a small overhead in longjmp(),
    alloca() can be implemented as efficiently as malloc() or better
    on any machine that can support C
I outlined the method in an earlier posting.

Whether alloca() is _worth_ implementing is another question.
-- 
I am not now and never have been a member of Mensa.		-- Ariadne.