[comp.lang.c] Using setjmp/longjmp

throopw@sheol.UUCP (Wayne Throop) (05/07/90)

> From: martin@mwtech.UUCP (Martin Weitzel)
> [...] malloc [...] interferes with setjmp/longjmp

Pardon?  In what way?
--
Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw@rti.rti.org

richard@aiai.ed.ac.uk (Richard Tobin) (05/08/90)

In article <0654@sheol.UUCP> throopw@sheol.UUCP (Wayne Throop) writes:
>> [...] malloc [...] interferes with setjmp/longjmp
>Pardon?  In what way?

I think the poster meant that it's difficult to use longjmp() to abort
to your program's main loop and at the same time clean up memory
allocated "on the way down".

The problem is the lack of an "unwind-protect" function, which would cause
longjmp() to execute "clean-up" code as it unwinds the stack (which of
course it doesn't in most implementations).

It shouldn't be too hard to synthesise something like Lisp's
catch/throw/unwind-protect.  Catch would call setjmp() and push (a
pointer to) the jmp_buf onto a stack.  Unwind_protect would take a
function as an argument and push it onto the same stack with a marker
identifying it as an unwind_protect.  Throw would pop jmp_buf's off
the stack, calling any unwind-protect functions it came to, until it
reached the target jmp_buf, which it would then longjmp() to.

Actually, it might be more convenient to have the clean-up code not be
a function, but just some code in the function calling unwind_protect.
This could be accomplished by having unwind_protect do a setjmp(), and
having throw longjmp() to it.  The only difficulty is having the
unwinding be resumed after the clean-up code.  This could probably be
done with some horrible macro hack so that you could write

  unwind_protect {
     ... clean-up code ...
  }

If you also want it to do the clean-ups when a function returns, this
will be rather harder.

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

peter@ficc.uu.net (peter da silva) (05/08/90)

> I think the poster meant that it's difficult to use longjmp() to abort
> to your program's main loop and at the same time clean up memory
> allocated "on the way down".

Rather than make this specific to longjmp, I tend to use a function
called "add_cleanup". This is passed a function name and a pointer to
a single argument, then when I want to clean things up I call
cleanup(), which pops all the functions off the stack and executes
them in turn.

For example:

	if(memory = malloc(...)) {
		add_cleanup(free, memory);
		...
	} else {
		errmsg = "Out of memory in foobar";
		longjmp(restart);
	}
-- 
`-_-' Peter da Silva. +1 713 274 5180.      <peter@ficc.uu.net>
 'U`  Have you hugged your wolf today?  <peter@sugar.hackercorp.com>
@FIN  Commercial solicitation *is* accepted by email to this address.