[Gc] Re: GC needs to be invoked manually

Boehm, Hans hans.boehm at hp.com
Tue Aug 30 14:53:37 PDT 2005


I'm sorry I didn't have a chance to look at this thread until now.

Traceable_allocator and GC_MALLOC_UNCOLLECTABLE allocate memory that
is traced for pointers by the collector (i.e. such objects are
viewed as always reachable, and anything they point to is also
reachable.)  Hence I think the behavior you saw earlier is the expected
behavior.

I don't see the behavior you describe below.  But I do see that many
objects
do not have their destructor called.  If I insert the GC_FREE call,
nearly all objects do have their destructors called.  This is also
expected,
but for more complicated reasons:

- The program below, as written, leaks memory.  Lots of it, since the
arrays
are not collectable.  Hence the heap grows substantially and without
bound.
There is nothing the collector can do about that, since it was asked not
to
collect this memory.

- The collector tries to trigger a GC every N bytes, where N is
proportional
to the heap or live data size.  Reasonable garbage collectors generally
need to do that, since otherwise the amount of GC time spent per byte
allocated gets larger and larger as the heap grows.  Which is bad.

- Since the heap is growing without bound, collections are triggered
less
and less frequently.  Hence the expected number of objects that were
allocated since the last GC gets larger and larger.  These won't
have their destructors run when the program finishes unless you insert
an explicit GC_gcollect() call.

- It may be that in your environment no collections take place between
the program starts and the time it exits.  Set the GC_PRINT_STATS
environment variable to verify.

Hans


> -----Original Message-----
> From: gc-bounces at napali.hpl.hp.com 
> [mailto:gc-bounces at napali.hpl.hp.com] On Behalf Of Martin Wartens
> Sent: Friday, August 26, 2005 1:57 PM
> To: gc at napali.hpl.hp.com
> Subject: [Gc] Re: GC needs to be invoked manually
> 
> 
> Meanwhile I discovered that I have to replace "traceable_allocator" 
> with "gc_allocator" to make the sample program work. 
> traceable_allocator uses 
> MALLOC_UNCOLLECTABLE internally. There seems to be some problem with 
> MALLOC_UNCOLLECTABLE. The test program below exposes this 
> problem. There is a 
> collectable class Element which creates a dynamic array on 
> initialization. If 
> MALLOC_UNCOLLECTABLE is used for allocating the array, no 
> Element object is 
> ever collected. This behavior also depends on the size of the 
> array. Collection 
> fails if the array has more than 26 entries (=104 bytes).
> 
> 
> #include <iostream>
> using namespace std;
> #include "gc_cpp.h"
> 
> struct Element: public gc_cleanup
> {
> 	static unsigned created;
> 	static unsigned destroyed;
> 	int* dynarray;
> 	Element(unsigned size)
> 	{
> 		/*this does not work*/
> 		dynarray = (int*) GC_MALLOC_UNCOLLECTABLE( size 
> * sizeof(int) );
> 
> 		/*the following three variants work*/
> 		//dynarray = (int*) GC_MALLOC_ATOMIC( size * 
> sizeof(int) );
> 		//dynarray = (int*) malloc( size * sizeof(int) );
> 		//dynarray = new int[size];
> 
> 		for(unsigned i=0; i<size; i++)
> 		{
> 			dynarray[i] = 0;
> 		}
> 		++created;
> 	}
> 
> 	~Element()
> 	{
> 		/*call appropriate free here*/
> 		//delete[] dynarray;
> 		//free(dynarray);
> 		//GC_FREE(dynarray);
> 		++destroyed;
> 	}
> 	private:
> 	Element(const Element& n){ }
> };
> unsigned Element::created(0);
> unsigned Element::destroyed(0);
> 
> //last working size with MALLOC_UNCOLLECTABLE is 26
> #define SIZE 27
> void testgc(){
> 	for (unsigned i=0; i<20000; i++)
> 	{
> 		Element *root = new Element(SIZE);
> 	}
> 	cout << "Elements created: " << Element::created << endl;
> 	cout << "Elements destroyed: " << Element::destroyed << endl; }
> 
> int main(int argc,char **argv)
> {
> 	testgc();
> }
> 
> 
> 
> 
> 
> _______________________________________________
> Gc mailing list
> Gc at linux.hpl.hp.com 
> http://www.hpl.hp.com/hosted/linux/mail-archives/gc/
> 



More information about the Gc mailing list