diff --git a/src/gc.c b/src/gc.c
index 7760c475cd386250a3b68e1a12d3a1b6a8674428..5b88f12adf218b38835754f1d20310a69b5929a7 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -30,7 +30,7 @@ struct callback *gc_evaluator_callback=0;
 
 #include "block_alloc.h"
 
-RCSID("$Id: gc.c,v 1.131 2000/09/04 14:28:08 grubba Exp $");
+RCSID("$Id: gc.c,v 1.132 2000/09/04 23:08:33 grubba Exp $");
 
 /* Run garbage collect approximately every time
  * 20 percent of all arrays, objects and programs is
@@ -1860,40 +1860,56 @@ int gc_do_free(void *a)
   return !(m->flags & GC_LIVE);
 }
 
+static void free_obj_arr(void *oa)
+{
+  struct array *obj_arr = *((struct array **)oa);
+
+  if (obj_arr) free_array(obj_arr);
+  free(oa);
+}
+
 static void warn_bad_cycles()
 {
-  JMP_BUF uwp;
-  struct array *obj_arr = 0;
+  /* The reason for the extra level of indirection, is that it might
+   * be clobbered by the longjump() in SET_ONERROR otherwise.
+   * (On some architectures longjump() might restore obj_arr's original
+   * value (eg if obj_arr is in a register)).
+   */
+  struct array **obj_arr_ = (struct array **)xalloc(sizeof(struct array *));
+  ONERROR tmp;
+
+  *obj_arr_ = NULL;
+
+  SET_ONERROR(tmp, free_obj_arr, obj_arr_);
 
-  if (!SETJMP(uwp)) {
+  {
     struct gc_frame *p;
     unsigned cycle = 0;
-    obj_arr = allocate_array(0);
+    *obj_arr_ = allocate_array(0);
 
     for (p = kill_list; p;) {
       if ((cycle = CYCLE(p))) {
 	push_object((struct object *) p->data);
-	obj_arr = append_array(obj_arr, --sp);
+	*obj_arr_ = append_array(*obj_arr_, --sp);
       }
       p = NEXT(p);
       if (p ? ((unsigned)(CYCLE(p) != cycle)) : cycle) {
-	if (obj_arr->size >= 2) {
+	if ((*obj_arr_)->size >= 2) {
 	  push_constant_text("gc");
 	  push_constant_text("bad_cycle");
-	  push_array(obj_arr);
-	  obj_arr = 0;
+	  push_array(*obj_arr_);
+	  *obj_arr_ = 0;
 	  SAFE_APPLY_MASTER("runtime_warning", 3);
 	  pop_stack();
-	  obj_arr = allocate_array(0);
+	  *obj_arr_ = allocate_array(0);
 	}
-	else obj_arr = resize_array(obj_arr, 0);
+	else *obj_arr_ = resize_array(*obj_arr_, 0);
       }
       if (!p) break;
     }
   }
 
-  UNSETJMP(uwp);
-  if (obj_arr) free_array(obj_arr);
+  CALL_AND_UNSET_ONERROR(tmp);
 }
 
 int do_gc(void)