diff --git a/src/gc.c b/src/gc.c
index 468212808f2139ca9409e8c7ddc8b050c6a511ba..8c944de87285e44c374ecccdc6b240cc6232d1a5 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -29,7 +29,7 @@ struct callback *gc_evaluator_callback=0;
 
 #include "block_alloc.h"
 
-RCSID("$Id: gc.c,v 1.71 2000/04/19 18:06:45 mast Exp $");
+RCSID("$Id: gc.c,v 1.72 2000/04/19 21:25:33 mast Exp $");
 
 /* Run garbage collect approximate every time we have
  * 20 percent of all arrays, objects and programs is
@@ -151,7 +151,7 @@ void describe_location(void *real_memblock,
   if(!location) return;
 /*  fprintf(stderr,"**Location of (short) svalue: %p\n",location); */
 
-  if(real_type!=-1) real_memblock=memblock;
+  if(real_type!=-1) memblock=real_memblock;
 
 #ifdef DEBUG_MALLOC
   if(memblock == 0 || type == -1)
@@ -506,7 +506,7 @@ void describe_something(void *a, int t, int indent, int depth, int flags)
   } else
 #endif /* DEBUG_MALLOC */
   if (((int)a) & 3) {
-    fprintf(stderr,"%*s**Location: %p  Type: %s  Missaligned address\n",indent,"",a,
+    fprintf(stderr,"%*s**Location: %p  Type: %s  Misaligned address\n",indent,"",a,
 	    get_name_of_type(t));
   } else {
     fprintf(stderr,"%*s**Location: %p  Type: %s  Refs: %d\n",indent,"",a,
@@ -514,13 +514,13 @@ void describe_something(void *a, int t, int indent, int depth, int flags)
 	    *(INT32 *)a);
   }
 
-  low_describe_something(a,t,indent,depth,flags);
-
 #ifdef DEBUG_MALLOC
   if(!(flags & DESCRIBE_NO_DMALLOC))
     debug_malloc_dump_references(a,indent+2,depth-1,flags);
 #endif
 
+  low_describe_something(a,t,indent,depth,flags);
+
   
   fprintf(stderr,"%*s*******************\n",indent,"");
   d_flag=tmp;
@@ -571,7 +571,7 @@ void debug_describe_svalue(struct svalue *s)
 INT32 real_gc_check(void *a)
 {
   struct marker *m=get_marker(a);
-  
+
 #ifdef PIKE_DEBUG
   if(check_for)
   {
@@ -597,6 +597,9 @@ INT32 real_gc_check(void *a)
     return 0;
   }
 
+  if (Pike_in_gc != 1)
+    fatal("gc check attempted in pass %d.\n", Pike_in_gc);
+
   if(m->saved_refs != -1)
     if(m->saved_refs != *(INT32 *)a) {
       fprintf(stderr,"**Refs changed in gc() pass %d. Expected %ld, got %ld.\n",
@@ -807,6 +810,11 @@ int gc_mark(void *a)
   struct marker *m;
   m=get_marker(debug_malloc_pass(a));
 
+#ifdef PIKE_DEBUG
+  if (Pike_in_gc != 2)
+    fatal("gc mark attempted in pass %d.\n", Pike_in_gc);
+#endif
+
   if(m->flags & GC_REFERENCED)
   {
     return 0;
@@ -870,6 +878,8 @@ void do_gc(void)
     gc_evaluator_callback=0;
   }
 
+  remove_objects_to_destruct_callback();
+
   tmp2=num_objects;
 
 #ifdef PIKE_DEBUG
diff --git a/src/gc.h b/src/gc.h
index b1857a516ed91d52088f7be41a357ee207547af6..b539f0ffa816c0a3339c4ed4c346f4b7d8fa1273 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -1,5 +1,5 @@
 /*
- * $Id: gc.h,v 1.35 2000/04/19 16:05:19 mast Exp $
+ * $Id: gc.h,v 1.36 2000/04/19 21:25:33 mast Exp $
  */
 #ifndef GC_H
 #define GC_H
@@ -125,7 +125,10 @@ void f__gc_status(INT32 args);
 #define GC_REFERENCED 1
 #define GC_XREFERENCED 2
 #define GC_CHECKED 4
-
+#ifdef PIKE_DEBUG
+#define GC_DO_FREE_OBJ 8
+#define GC_OBJ_PASS_4 16
+#endif
 
 #ifdef PIKE_DEBUG
 #define gc_is_referenced(X) debug_gc_is_referenced(debug_malloc_pass(X))
diff --git a/src/object.c b/src/object.c
index 27e93791d15804df12b49accb47b46f26ddc5cb6..30398435c1a88ab93d1c8908751326a2041c7fdf 100644
--- a/src/object.c
+++ b/src/object.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: object.c,v 1.113 2000/04/19 14:00:43 mast Exp $");
+RCSID("$Id: object.c,v 1.114 2000/04/19 21:25:33 mast Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -551,6 +551,15 @@ void destruct(struct object *o)
 static struct object *objects_to_destruct = 0;
 static struct callback *destruct_object_evaluator_callback =0;
 
+void remove_objects_to_destruct_callback(void)
+{
+  if(destruct_object_evaluator_callback)
+  {
+    remove_callback(destruct_object_evaluator_callback);
+    destruct_object_evaluator_callback=0;
+  }
+}
+
 /* This function destructs the objects that are scheduled to be
  * destructed by really_free_object. It links the object back into the
  * list of objects first. Adds a reference, destructs it and then frees it.
@@ -560,6 +569,11 @@ void destruct_objects_to_destruct(void)
   struct object *my_list=0;
   struct object *o, *next;
 
+#ifdef PIKE_DEBUG
+  if (Pike_in_gc >= 3 && Pike_in_gc <= 4)
+    fatal("Can't meddle with the object link list in gc pass %d.\n", Pike_in_gc);
+#endif
+
   while((o=objects_to_destruct))
   {
     /* Link object back to list of objects */
@@ -576,11 +590,7 @@ void destruct_objects_to_destruct(void)
     free_object(o);
   }
 
-  if(destruct_object_evaluator_callback)
-  {
-    remove_callback(destruct_object_evaluator_callback);
-    destruct_object_evaluator_callback=0;
-  }
+  remove_objects_to_destruct_callback();
 }
 
 
@@ -606,6 +616,8 @@ void really_free_object(struct object *o)
 
   if(o->prog)
   {
+    DOUBLELINK(objects_to_destruct,o);
+    if (Pike_in_gc) return;	/* Done last in gc(). */
     if(!destruct_object_evaluator_callback)
     {
       destruct_object_evaluator_callback=
@@ -613,8 +625,6 @@ void really_free_object(struct object *o)
 			(callback_func)destruct_objects_to_destruct,
 			0,0);
     }
-
-    DOUBLELINK(objects_to_destruct,o);
   } else {
     if(o->parent)
     {
@@ -1244,9 +1254,15 @@ void gc_free_all_unreferenced_objects(void)
 
   for(o=first_object;o;o=o->next)
   {
+#ifdef PIKE_DEBUG
+    get_marker(o)->flags |= GC_OBJ_PASS_4;
+#endif
     if(gc_do_free(o))
     {
       add_ref(o);
+#ifdef PIKE_DEBUG
+      get_marker(o)->flags |= GC_DO_FREE_OBJ;
+#endif
       call_destroy(o,0);
     }
   }
@@ -1255,6 +1271,18 @@ void gc_free_all_unreferenced_objects(void)
   {
     if(gc_do_free(o))
     {
+#ifdef PIKE_DEBUG
+      if (!(get_marker(o)->flags & GC_DO_FREE_OBJ) ||
+	  !(get_marker(o)->flags & GC_OBJ_PASS_4)) {
+	extern char *fatal_after_gc;
+	fprintf(stderr,"**Object unexpectedly marked for gc. flags: %d\n",
+		get_marker(o)->flags);
+	describe(o);
+	locate_references(o);
+	fprintf(stderr,"##### Continuing search for more bugs....\n");
+	fatal_after_gc="Object unexpectedly marked for gc.\n";
+      }
+#endif
       low_destruct(o,1);
       SET_NEXT_AND_FREE(o,free_object);
     }else{
diff --git a/src/object.h b/src/object.h
index ffe23ee9597d19e6b9345424e8b5b5264c409436..ab20a180aa894876d7dbc690f9b26fd844cc66bd 100644
--- a/src/object.h
+++ b/src/object.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: object.h,v 1.41 2000/04/13 20:14:35 hubbe Exp $
+ * $Id: object.h,v 1.42 2000/04/19 21:25:33 mast Exp $
  */
 #ifndef OBJECT_H
 #define OBJECT_H
@@ -66,6 +66,7 @@ struct destroy_called_mark;
 PTR_HASH_ALLOC(destroy_called_mark,128)
 void low_destruct(struct object *o,int do_free);
 void destruct(struct object *o);
+void remove_objects_to_destruct_callback(void);
 void destruct_objects_to_destruct(void);
 void really_free_object(struct object *o);
 void low_object_index_no_free(struct svalue *to,