[gclist] Boehm gc with STL from gcc 2.95.2?

Boehm, Hans hans_boehm@hp.com
Mon, 17 Apr 2000 14:17:38 -0700


This is expected behavior.  You are running into two issues:

1) A conservative collector usually can't tell precisely when something goes
out of scope.  The pointer value may still persist in a stack location
that's not immediately overwritten, or in a register.  This usually results
in some unnecessary object retention, but this is rearely very significant
in real programs.  If you put your main program inside a loop, you should
see things reclaimed over time.

2) The default finalization mechanism ensures that you don't accidentally
see previously finalized objects from inside a finalizer.  This means that
immediately after your explicit garbage collection, only the first FooLink
in the list can be safely finalized.  If you finalized any other object, a
subsequent finalizer could see a previously finalized FooLink.  The net
effect is that only one FooLink is finalized per GC cycle.  (This implies
that if the FooLink doesn't really need to access the next field, you should
probably let the garbage collector know this, e.g. by instead finalizing an
object referenced from FooLink instead of FooLink itself.  Alternatively,
you can get the collector to use Java-like finalization semantics, but then
you need to be more careful about accessing previously finalized objects,
particularly if they are wrappers for explicitly deallocated objects.)

There are more details at

http://www.hpl.hp.com/personal/Hans_Boehm/gc/finalization.html

Hans

-----Original Message-----
From: Benjamin Geer [mailto:benjamin.geer@btinternet.com]
Sent: Monday, April 17, 2000 12:26 PM
To: gclist@iecc.com
Cc: Boehm, Hans
Subject: Re: [gclist] Boehm gc with STL from gcc 2.95.2?


I think there might be a problem with gc_cpp.  The following test
program makes a singly-linked list, in which the links are derived
from gc_cleanup, as is the data in each link.  The output shows that
none of the data objects are reclaimed.  When I change it so that
FooLink is derived from gc instead of gc_cleanup, all of them are
reclaimed.  Perhaps I've misunderstood, but it seems to me that it
should work either way, since there are no circular references
involved.

Ben

#include <gc_cpp.h>
#include <iostream>

using namespace std;

int numCreated = 0;
int numDeleted = 0;

// Each link will contain one of these.
class Foo : public gc_cleanup {
public:
    Foo() {
        ++numCreated;
    }

    ~Foo() {
        ++numDeleted;
    }
};

// Links in a linked list.
struct FooLink : public gc_cleanup {
    Foo* foo;
    FooLink* next;

    FooLink(Foo* arg_foo) : foo(arg_foo), next(0) { }
};

// Makes a linked list with 10000 links, then lets it go out of scope.
void makeFoos() {
    Foo* first = new Foo();
    FooLink* head = new FooLink(first);
    FooLink* tail = head;

    for (int i = 0; i < 9999; ++i) {
        Foo* foo = new Foo;
        FooLink* next = new FooLink(foo);
        tail->next = next;
        tail = next;
    }
}

int main(int argc, char* argv[]) {
    makeFoos();

    GC_gcollect();

    cout << numCreated << " created, " << numDeleted << " deleted" << endl;

    return 0;
}