structure function returns -- how?

Henry Spencer henry at utzoo.UUCP
Sat Dec 20 05:09:06 AEST 1986


> (c) Function allocates static space and returns pointer.  Caller copies.
> 
>     This is not reentrant, as has been pointed out.  Nor does it work if
>     the function is recursive...

Not true, given proper code generation.  The static area need be in use
only during the return sequence, hence recursion is no problem -- execution
of multiple instances of a recursive function overlaps, but the return
sequences need not.  Static-area return values may even speed up recursive
returns, since less copying may be needed.  Reentrancy is another story,
although it should be noted that reentrancy is another story for a *whole*
*lot* of things in a C/Unix environment:  a signal handler has to be very
careful, since locking out signal handlers during critical sections in (say)
stdio is expensive and hence seldom done.

>(e) Function leaves result on stack.
>
>    This is usually easiest for the function.  The problem is that on many
>    systems an interrupt or signal will destroy the result.  (flame)(This is a
>    symptom of a major and persistent system design error: the use of a
>    hardware register pointing into user space as a place to dump junk.  It
>    is compounded by language implementations that use the hardware stack
>    to allocate the LIFO address space of local variables)...

No, it's a symptom of a major and persistent software error:  using a stack
pointer as if it were an index register.  If you get it firmly into your
head that you are dealing with a *stack*, not just an index register that
happens to increment and decrement automatically in some circumstances,
then the problem goes away.  When you say "leaves result on stack", what
you really mean is "leaves result beyond the end of the stack, assuming that
the stack will not be used as a stack until the result is picked up".  It
is possible, although often awkward, to leave the result *on the stack*,
i.e. as if it had been pushed onto the stack, in which case there isn't a
problem with interrupts or signals.  (This is approximately what your e3
alternative does, but in an unnecessarily roundabout way using a magic
run-time routine.)

> (d) Function allocates heap space, rest as above.
> 
>     ...always works but can be rather expensive.

It always works in the absence of reentrancy, or if your memory allocator
is reentrant, which many aren't.

Additional alternatives that you have missed are some variations on (b)
(caller preallocates):  (1) it isn't necessary for the address to be passed
as a parameter if the caller and callee can establish mutual agreement
on where the result goes, although this is generally practical only if
the stack is contiguous; (2) it may be possible to use the argument area
as the return area, if the caller ensures it is big enough and avoids
popping it off the stack or re-using it before picking up the result,
and the callee makes sure that result copying comes after all uses of
arguments (especially in the case where the returned value is the value
of an argument).

[Incidentally, it reflects badly on you to chide us for re-inventing the
wheel when you seem not to be aware of some of the prior art yourself.
You might find Bell Labs Computing Science Tech Report No. 102, "The C
Language Calling Sequence", by Johnson and Ritchie, Sept. 1981, to be
interesting reading.]
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry



More information about the Comp.lang.c mailing list