diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index d320aff2f195faff79f4bad7de9e785d4baab62d..8692a049ab29dd4d758c2bd015c97b84a350575c 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -6,7 +6,7 @@
 #define READ_BUFFER 16384
 
 #include "global.h"
-RCSID("$Id: file.c,v 1.23 1997/01/26 22:49:40 per Exp $");
+RCSID("$Id: file.c,v 1.24 1997/01/28 03:28:45 hubbe Exp $");
 #include "types.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -1336,13 +1336,30 @@ void exit_files()
   free_program(file_program);
 }
 
+void mark_ids(struct callback *foo, void *bar, void *gazonk)
+{
+  int e;
+  for(e=0;e<MAX_OPEN_FILEDESCRIPTORS;e++)
+  {
+    gc_check_svalues( & files[e].id, 1);
+    gc_check_svalues( & files[e].close_callback, 1);
+  }
+}
 
 void init_files_programs()
 {
+  int e;
+  for(e=0;e<MAX_OPEN_FILEDESCRIPTORS;e++)
+  {
+    init_fd(e, 0);
+    files[e].refs=0;
+  }
+
   init_fd(0, FILE_READ);
   init_fd(1, FILE_WRITE);
   init_fd(2, FILE_WRITE);
 
+
   start_new_program();
   add_storage(sizeof(struct file_struct));
 
@@ -1391,5 +1408,7 @@ void init_files_programs()
   file_program->refs++;
 
   port_setup_program();
+
+  add_gc_callback(mark_ids, 0, 0);
 }
 
diff --git a/src/program.c b/src/program.c
index 8e1efee02705551232bbadfc29a649c3c1e7a8d7..34c306c86a05051dca90acd6dec610715062611d 100644
--- a/src/program.c
+++ b/src/program.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: program.c,v 1.15 1997/01/27 01:30:25 hubbe Exp $");
+RCSID("$Id: program.c,v 1.16 1997/01/28 03:11:50 hubbe Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -1558,7 +1558,22 @@ void gc_check_all_programs()
 {
   struct program *p;
   for(p=first_program;p;p=p->next)
+  {
     gc_check_svalues(p->constants, p->num_constants);
+
+    if(d_flag)
+    {
+      int e;
+      for(e=0;e<(int)p->num_strings;e++)
+	gc_check(p->strings[e]);
+
+      for(e=0;e<(int)p->num_identifiers;e++)
+      {
+	gc_check(p->identifiers[e].name);
+	gc_check(p->identifiers[e].type);
+      }
+    }
+  }
 }
 
 void gc_mark_all_programs()
diff --git a/src/stralloc.c b/src/stralloc.c
index 4d8d4c0c82aec71e0fb18db3e6571f628221429c..104729e4f890b0a34f659ebac306fdf195212ba2 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -201,6 +201,18 @@ void unlink_pike_string(struct pike_string *s)
 
 void really_free_string(struct pike_string *s)
 {
+#ifdef DEBUG
+  extern int d_flag;
+  if(d_flag > 2)
+  {
+    if(s->next == (struct pike_string *)-1)
+      fatal("Freeing shared string again!\n");
+      
+    unlink_pike_string(s);
+    s->next=(struct pike_string *)-1;
+    return;
+  }
+#endif
   unlink_pike_string(s);
   free((char *)s);
 }
@@ -548,3 +560,17 @@ void count_memory_in_strings(INT32 *num, INT32 *size)
   num[0]=num_;
   size[0]=size_;
 }
+
+#ifdef GC2
+
+void gc_mark_all_strings()
+{
+  unsigned INT32 e;
+  if(!base_table) return;
+  for(e=0;e<htable_size;e++)
+  {
+    struct pike_string *p;
+    for(p=base_table[e];p;p=p->next) gc_is_referenced(p);
+  }
+}
+#endif
diff --git a/src/stralloc.h b/src/stralloc.h
index df7271361223e7dbdd47d5cf90c7dd1e086df409..22b5fe0a961f43fc2156bb56454c09413022e714 100644
--- a/src/stralloc.h
+++ b/src/stralloc.h
@@ -14,7 +14,7 @@
 #endif
 struct pike_string
 {
-  SIZE_T refs;
+  INT32 refs;
   INT32 len;
   unsigned INT32 hval;
   struct pike_string *next; 
@@ -25,7 +25,7 @@ struct pike_string
 struct pike_string *debug_findstring(const struct pike_string *foo);
 #endif
 
-#define free_string(s) do{ struct pike_string *_=(s); if(!--_->refs) really_free_string(_); }while(0)
+#define free_string(s) do{ struct pike_string *_=(s); if(--_->refs<=0) really_free_string(_); }while(0)
 
 #define my_hash_string(X) ((unsigned long)(X))
 #define my_order_strcmp(X,Y) ((char *)(X)-(char *)(Y))
@@ -60,6 +60,7 @@ struct pike_string *string_replace(struct pike_string *str,
 void init_shared_string_table();
 void cleanup_shared_string_table();
 void count_memory_in_strings(INT32 *num, INT32 *size);
+void gc_mark_all_strings();
 /* Prototypes end here */
 
 #endif /* STRALLOC_H */
diff --git a/src/svalue.c b/src/svalue.c
index 5bcf381c95398e9abd2b60b57644e17685e35e1a..8415202d1b610f73dee099593c371d80aa351c3e 100644
--- a/src/svalue.c
+++ b/src/svalue.c
@@ -166,7 +166,7 @@ void free_svalues(struct svalue *s,INT32 num, INT32 type_hint)
   case BIT_FUNCTION:
     while(--num>=0)
     {
-      if(s->u.refs[0]--==0)
+      if(s->u.refs[0]-- <= 0)
       {
 	if(s->subtype == FUNCTION_BUILTIN)
 	  really_free_callable(s->u.efun);
@@ -833,12 +833,27 @@ TYPE_FIELD gc_check_svalues(struct svalue *s, int num)
   INT32 e;
   TYPE_FIELD f;
   f=0;
+
   for(e=0;e<num;e++,s++)
   {
+    check_type(s->type);
+    check_refs(s);
+    
     switch(s->type)
     {
     case T_FUNCTION:
-      if(s->subtype == FUNCTION_BUILTIN) break;
+      if(s->subtype == FUNCTION_BUILTIN)
+      {
+	if(d_flag)
+	{
+	  if(!gc_check(s->u.efun))
+	  {
+	    gc_check(s->u.efun->name);
+	    gc_check(s->u.efun->type);
+	  }
+	}
+	break;
+      }
 
     case T_OBJECT:
       if(s->u.object->prog)
@@ -851,12 +866,15 @@ TYPE_FIELD gc_check_svalues(struct svalue *s, int num)
       }
       break;
 
+    case T_STRING:
+      if(!d_flag) break;
     case T_PROGRAM:
     case T_ARRAY:
     case T_MULTISET:
     case T_MAPPING:
       gc_check(s->u.refs);
       break;
+
     }
     f|= 1 << s->type;
   }
@@ -882,6 +900,8 @@ void gc_check_short_svalue(union anything *u, TYPE_T type)
     }
     break;
 
+  case T_STRING:
+    if(!d_flag) break;
   case T_ARRAY:
   case T_MULTISET:
   case T_MAPPING: