This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: forcing guile to collect *all* garbage?


Jon Trowbridge <trow@emccta.com> writes:

> On Mon, Apr 12, 1999 at 05:27:25PM -0230, Greg Harvey wrote:
> > Jon Trowbridge <trow@emccta.com> writes:
> > 
> > > Is there anything that I can do to trigger an "aggressive" garbage
> > > collection in guile, in which the whole heap would be scanned and I
> > > could be sure afterwards that every lingering unreferenced object had
> > > been deallocated?
> > 
> > That is how the gc currently operates (though I might not be
> > understanding you correctly). If a dead object is hanging around, it
> > means that either it's being scanned conservatively,
> 
> What does it mean to be "scanned conservatively"?

It means that somewhere on the c stack, there's a value (which could
be a pointer, or could just be an integer) that looks like it's
pointing into the heap at that object. From the example below, though,
I don't think this is the problem. If you do want to make absolutely
sure that this isn't what's causing the problem, you could add the
following patch (might be a bit of fuzz):

*** gc.c.orig	Tue Apr 13 23:34:20 1999
--- gc.c	Tue Apr 13 23:45:29 1999
***************
*** 937,944 ****
  		  }
  		if (   !scm_heap_table[seg_id].valid
  		    || scm_heap_table[seg_id].valid (ptr,
! 						     &scm_heap_table[seg_id]))
  		  scm_gc_mark (*(SCM *) & x[m]);
  		break;
  	      }
  
--- 937,946 ----
  		  }
  		if (   !scm_heap_table[seg_id].valid
  		    || scm_heap_table[seg_id].valid (ptr,
! 						     &scm_heap_table[seg_id])) {
!                   fprintf(stderr, "Conservatively marking %#lx\n", *(SCM *) & x[m]);
  		  scm_gc_mark (*(SCM *) & x[m]);
+                 }
  		break;
  	      }
  
And check that, after the gc, the object that isn't being collected
isn't in that list (it does cause a lot of screen spam on startup,
though ;).

> 
> Well, here is an example of what I'm talking about.  I have some C
> code that handles date math that I've hooked into guile via a smob.
> I've hacked that smob to print a message whenever an object is
> allocated or freed.  Here is an trivial, annotated example of such an
> interaction.
> 
> guile> (date 1 1 2000) <== This constructs a date object.
> Alloced 0x80b67a8
> 01/01/2000

Is this going through scm printing functions, or just printf? (I'm
assuming scheme, at least for the date).

> guile> (date 1 3 2000)
> Alloced 0x80b66a8
> 01/03/2000
> guile> (gc)
> Freed 0x80b69a0        <== The second object was freed.  The third remains.
> guile> (gc)
> guile> (gc)
> guile> (gc)
> guile> (gc)            <== <grumble> I can't get rid of the third object.
> guile> (cons 1 2)      <== But if I perform a useless operation that allocates
> (1 . 2)                    a new cell...
> guile> (gc)
> Freed 0x80b66a8        <== ...the third object finally goes away!
> 
> This might seem like a minor thing, but it is causing me big
> problems.

It's not a minor problem at all. Things get worse if you display a
weak-hash, because the unreferenced key or value doesn't seem to
*ever* be collected, even if the only true reference is from the
weak-hash.

> At certain key points in my interfaced C++ code, I need to be able to
> put myself into a state where I know that all of the old objects of a
> certain type have been freed, so that I can perform some operations
> that would cause pointers inside those objects to become "dangling"
> and thus unsafe.  But the reference counts on my old objects won't
> reliably go to zero, because of lingering guile objects.
> 
> If this is being caused by the printer, is there anything that can
> reasonably be done about it?

I'm not quite sure yet (I haven't spent much time with the printer);
possibly a function that flushes out the print states or, maybe better
would be implementing the refstack of a print state with a weak vector
+ an additional list which is dropped on exit from print function, so
that the object doesn't die during printing.

-- 
Greg