SGCL - Garbage Collector for C++

85 views
Skip to first unread message

Sebastian Nibisz

unread,
Feb 28, 2008, 9:09:59 AM2/28/08
to
SGCL is precise, parallel garbage collection library for C++ (at this time
for Windows 32/64 only). SGCL is free software published under University of
Illinois/NCSA Open Source License.

Get it at:
http://sourceforge.net/projects/sgcl/

Regards
Sebastian Nibisz

mosfet

unread,
Feb 28, 2008, 9:13:51 AM2/28/08
to
Sebastian Nibisz a écrit :

If you need garbage collection you should try D language.

Linonut

unread,
Feb 28, 2008, 9:49:53 AM2/28/08
to
* Sebastian Nibisz peremptorily fired off this memo:

> SGCL is precise, parallel garbage collection library for C++ (at this time
> for Windows 32/64 only).

Ridiculous.

> SGCL is free software published under University of
> Illinois/NCSA Open Source License.

--
When the PC was launched, people knew it was important.
-- Bill Gates

Sebastian Nibisz

unread,
Feb 28, 2008, 9:59:28 AM2/28/08
to
> If you need garbage collection you should try D language.

The D language doesn't have the parallel garbage collector.

Regards
Sebastian Nibisz

Christopher

unread,
Feb 28, 2008, 10:57:24 AM2/28/08
to

Garbage collection is for lazy rich folks who can't be bothered to
take out their own trash.

Sebastian Nibisz

unread,
Feb 28, 2008, 11:07:24 AM2/28/08
to
> Garbage collection is for lazy rich folks who can't be bothered to
> take out their own trash.

It's funny.

Sebastian Nibisz

unread,
Feb 28, 2008, 11:26:12 AM2/28/08
to
> Garbage collection is for lazy rich folks who can't be bothered to
> take out their own trash.

struct node
{
node* next;
};

node* root = new node;
node* n = root;

for (int x = 0; x < 1000000; ++x)
{
n = n->next = new node;
}

How to release memory?

Alberto Bignotti

unread,
Feb 28, 2008, 11:58:06 AM2/28/08
to
node* root = new node;
node* n = root;

for (int x = 0; x < 10; ++x)


{
n = n->next = new node;

n->next = 0;
}

n=root;
while(n){
root=n;
n=n->next;
delete root;
}

is that 6 lines too much for you?
if your reply is yes then use a GC.
Be happy.

"Sebastian Nibisz" <EB...@poczta.onet.pl> ha scritto nel messaggio
news:fq6nba$rae$1...@inews.gazeta.pl...

Erik Wikström

unread,
Feb 28, 2008, 11:58:38 AM2/28/08
to

A recursive function?

--
Erik Wikström

Phil Endecott

unread,
Feb 28, 2008, 12:11:56 PM2/28/08
to

std::list<>
or boost::intrusive::list<>
or struct node { smart_pointer<node> next; };
or explicit destruction as Alberto described
or allocation from a pool which is all deallocated together
or garbage collection.

All have their advantages and disadvantages. Personally I'm happy with
std::list 99% of the time. I'm actually quite curious to know what sort
of applications or users use garbage collection in C++, but I fear that
it's the sort of discussion that can deteriorate....


Phil.

James Kanze

unread,
Feb 28, 2008, 12:22:00 PM2/28/08
to

> > struct node
> > {
> > node* next;
> > };

> > How to release memory?

> A recursive function?

:-).

Smart pointers. We all know that boost::shared_ptr is the
answer to all questions concerning pointers. So just replace
all of the pointers with boost::shared_ptr< node >.

Of course, this problem does have a fairly simple solution.
Most memory management problems do. It's just that it's not
always the same solution, so you have to do considerable
analysis to find it. I use the Boehm collector in new projects,
and it saves development time.

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Marcel Müller

unread,
Feb 28, 2008, 12:21:47 PM2/28/08
to
Sebastian Nibisz schrieb:

> struct node
> {
> node* next;
> };
>
> node* root = new node;
> node* n = root;
>
> for (int x = 0; x < 1000000; ++x)
> {
> n = n->next = new node;
> }
>
> How to release memory?

struct node
{ // content...
};

std::slist<boost::shared_ptr<node> > ?


or


struct node
{ boost::shared_ptr<node> next;
};


or if you look for very high performant solutions try
boost::intrusive_ptr which allows very small memory footprints of your
nodes because no additional heap objects are allocated at all.


In fact the only domain of GC solutions are complex data structures with
many cyclic references and without a parent child relation.


Marcel

Sebastian Nibisz

unread,
Feb 28, 2008, 12:36:04 PM2/28/08
to
> or
>
> struct node
> { boost::shared_ptr<node> next;
> };

{


for (int x = 0; x < 1000000; ++x)
{

n = n->next = shared_ptr<node>(new node);
}
} // <- STACK OVERFLOW


rgds
Sebastian Nibisz

Thomas J. Gritzan

unread,
Feb 28, 2008, 12:36:38 PM2/28/08
to
Erik Wikström schrieb:

Stack overflow?

--
Thomas
http://www.netmeister.org/news/learn2quote.html
To iterate is human, to recurse divine.
-L. Peter Deutsch

Phil Endecott

unread,
Feb 28, 2008, 1:25:28 PM2/28/08
to
Sebastian Nibisz wrote:
>> or
>>
>> struct node
>> { boost::shared_ptr<node> next;
>> };
>
> {
> for (int x = 0; x < 1000000; ++x)
> {
> n = n->next = shared_ptr<node>(new node);
> }
> } // <- STACK OVERFLOW

Why?

Jeff Schwab

unread,
Feb 28, 2008, 1:44:14 PM2/28/08
to

It's hard to guess why you would allocate nodes that way in the first place.

Sebastian Nibisz

unread,
Feb 28, 2008, 1:49:03 PM2/28/08
to
>> {
>> for (int x = 0; x < 1000000; ++x)
>> {
>> n = n->next = shared_ptr<node>(new node);
>> }
>> } // <- STACK OVERFLOW
>
> Why?

{
shared_ptr<node> root(new node);
shared_ptr<node> n(root);

for (int x = 0; x < 1000000; ++x)
{
n = n->next = shared_ptr<node>(new node);
}

} // <- recursive destruction (root)

rgds
Sebastian Nibisz

Sebastian Nibisz

unread,
Feb 28, 2008, 2:19:52 PM2/28/08
to
> for (int x = 0; x < 10; ++x)
> {
> n = n->next = new node;
> n->next = 0;
> }
>
> n=root;
> while(n){
> root=n;
> n=n->next;
> delete root;
> }

Ok. What if there is a cyclical list?

node* root = new node;
node* n = root;

node* r_n;

int r = rand() % 10;

for (int x = 0; x < 10; ++x)
{
n = n->next = new node;

if (x == r)
{
r_n = n;
}
}

n->next = r_n;

Sebastian Nibisz

unread,
Feb 28, 2008, 2:35:15 PM2/28/08
to
>> struct node
>> {
>> node* next;
>> };
>>
>> node* root = new node;
>> node* n = root;
>>
>> for (int x = 0; x < 1000000; ++x)
>> {
>> n = n->next = new node;
>> }
>>
>> How to release memory?
>
> It's hard to guess why you would allocate nodes that way in the first
> place.

The parent must know the child.

rgds
Sebastian Nibisz

James Kanze

unread,
Feb 28, 2008, 4:47:19 PM2/28/08
to
On Feb 28, 7:25 pm, Phil Endecott <spam_from_usenet_0...@chezphil.org>
wrote:
> Sebastian Nibisz wrote:
> >> or

> Why?

You're kidding us, right?

Eric was obviously being facious with his suggestion, since it
obviously wouldn't work; I can't imagine anyone not spotting the
problem immediately. The trick about shared_ptr, here, of
course, is that you don't see the recursion, so you may not
realize that you have the same problem until someone explicitly
asks what will happen.

It's really pretty rare that you can recurse 1000000 times
without the stack overflowing.

James Kanze

unread,
Feb 28, 2008, 4:54:00 PM2/28/08
to
On Feb 28, 6:11 pm, Phil Endecott <spam_from_usenet_0...@chezphil.org>
wrote:

> > struct node
> > {
> > node* next;
> > };

> > How to release memory?

Not really. There are those of us who are paid to produce
working code as inexpensively as possible. Garbage collection
saves some work in some specific cases (which do occur fairly
frequently, even if they don't represent the majority of dynamic
allocations), so we use it. Not doing so would be
irresponsible, from a professional point of view---something
like using <generic.h> instead of templates.

Naturally, of course:

-- objects with value semantics shouldn't be allocated
dynamically to begin with, so garbage collection won't
affect them,

-- even more obviously, the same thing holds for RAII
mangagers,

-- and generally, entity objects should manage their own
lifetimes---although using garbage collection here does
improve type safety, and allows catching some errors
(dangling pointers).

But there will usually be a few odd objects which don't fit into
one of the above categories, and garbage collection means one
less thing to code when using them (and the detection of
dangling pointers for entity objects isn't to be sneezed at if
you need robustness).

Ioannis Vranos

unread,
Feb 28, 2008, 5:15:09 PM2/28/08
to Sebastian Nibisz

Sounds like interesting stuff for anyone who wants to use GC in his/her
applications.

The thread shouldn't turn out to the flame "Do we need garbage
collection"? Anyone that can afford it in his/her applications and wants
to, he/she may use it.

Ioannis Vranos

unread,
Feb 28, 2008, 5:15:37 PM2/28/08
to

Sounds like interesting stuff for anyone who wants to use GC in his/her

Alf P. Steinbach

unread,
Feb 28, 2008, 5:16:05 PM2/28/08
to
* James Kanze:

> On Feb 28, 7:25 pm, Phil Endecott <spam_from_usenet_0...@chezphil.org>
> wrote:
>> Sebastian Nibisz wrote:
>>>> or
>
>>>> struct node
>>>> { boost::shared_ptr<node> next;
>>>> };
>
>>> {
>>> for (int x = 0; x < 1000000; ++x)
>>> {
>>> n = n->next = shared_ptr<node>(new node);
>>> }
>>> } // <- STACK OVERFLOW
>
>> Why?
>
> You're kidding us, right?
>
> Eric was obviously being facious with his suggestion, since it
> obviously wouldn't work; I can't imagine anyone not spotting the
> problem immediately. The trick about shared_ptr, here, of
> course, is that you don't see the recursion, so you may not
> realize that you have the same problem until someone explicitly
> asks what will happen.
>
> It's really pretty rare that you can recurse 1000000 times
> without the stack overflowing.

Huh?


Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Phil Endecott

unread,
Feb 28, 2008, 7:08:01 PM2/28/08
to
James Kanze wrote:
> On Feb 28, 7:25 pm, Phil Endecott <spam_from_usenet_0...@chezphil.org>
> wrote:
>> Sebastian Nibisz wrote:
>>>> or
>
>>>> struct node
>>>> { boost::shared_ptr<node> next;
>>>> };
>
>>> {
>>> for (int x = 0; x < 1000000; ++x)
>>> {
>>> n = n->next = shared_ptr<node>(new node);
>>> }
>>> } // <- STACK OVERFLOW
>
>> Why?
>
> You're kidding us, right?

James, that's pretty rude. I know this is usenet but I'd really
appreciate if if you could moderate the way you express yourself. I am
not "kidding you" when I say that I did not spot this problem, which is
why I asked "Why?". I have learnt something new and interesting this
evening. Why you had to chime in with that patronising phrase is beyond me.

Goodbye.

Sam

unread,
Feb 28, 2008, 7:53:02 PM2/28/08
to
Sebastian Nibisz writes:

It's true. If you do not have the skills and the know-how to keep track of
your own objects, and manage their lifetime, you have no business writing
mission-critical, business software.


Sam

unread,
Feb 28, 2008, 7:55:25 PM2/28/08
to
Sebastian Nibisz writes:

>> for (int x = 0; x < 10; ++x)
>> {
>> n = n->next = new node;
>> n->next = 0;
>> }
>>
>> n=root;
>> while(n){
>> root=n;
>> n=n->next;
>> delete root;
>> }
>
> Ok. What if there is a cyclical list?

Use your brain, and add two lines of code to the above fragment, making it
work for cyclical lists.

No, I'm not going to show you how to do it. I'm not sure you'll be able to
understand it.

Sam

unread,
Feb 28, 2008, 7:59:01 PM2/28/08
to
James Kanze writes:

> On Feb 28, 5:58 pm, Erik Wikström <Erik-wikst...@telia.com> wrote:
>> On 2008-02-28 17:26, Sebastian Nibisz wrote:
>
>> >> Garbage collection is for lazy rich folks who can't be
>> >> bothered to take out their own trash.
>
>> > struct node
>> > {
>> > node* next;
>> > };
>
>> > node* root = new node;
>> > node* n = root;
>
>> > for (int x = 0; x < 1000000; ++x)
>> > {
>> > n = n->next = new node;
>> > }
>
>> > How to release memory?
>
>> A recursive function?
>
> :-).
>
> Smart pointers. We all know that boost::shared_ptr is the
> answer to all questions concerning pointers. So just replace
> all of the pointers with boost::shared_ptr< node >.

No, please, not this horrible, stinking monstrosity called "Boost". The
other day I actually had the misfortune of looking how shared_ptr is
implemented, and nearly lost my lunch. Utterly clueless, brainless design. I
ended up coding my own version of shared_ptr, and benchmarked it 15% faster
than Boost's disgusting code.

Sebastian Nibisz

unread,
Feb 28, 2008, 8:49:12 PM2/28/08
to
I am impressed by your intelligence.

Sam

unread,
Feb 28, 2008, 9:06:29 PM2/28/08
to
Sebastian Nibisz writes:

> I am impressed by your intelligence.

You should be. You can't even manage the task of quoting the message you're
replying to, so that others actually may have a hint as to what in blazes
you're yammering about.

Jeff Schwab

unread,
Feb 28, 2008, 11:38:56 PM2/28/08
to

Sorry, I meant why not use a standard container to manage the nodes'
lifetimes? The slist mentioned elsewhere on this thread was a
reasonable suggestion, if std::list is too heavy.

Jeff Schwab

unread,
Feb 29, 2008, 12:05:04 AM2/29/08
to
Alf P. Steinbach wrote:
> * James Kanze:
>> On Feb 28, 7:25 pm, Phil Endecott <spam_from_usenet_0...@chezphil.org>
>> wrote:
>>> Sebastian Nibisz wrote:
>>>>> or
>>
>>>>> struct node
>>>>> { boost::shared_ptr<node> next;
>>>>> };
>>
>>>> {
>>>> for (int x = 0; x < 1000000; ++x)
>>>> {
>>>> n = n->next = shared_ptr<node>(new node);
>>>> }
>>>> } // <- STACK OVERFLOW
>>
>>> Why?
>>
>> You're kidding us, right?
...

>>
>> It's really pretty rare that you can recurse 1000000 times
>> without the stack overflowing.
>
> Huh?

I'm not sure it's obvious until you're been looking at it for a few
minutes, but given a program like the following:

#include <tr1/memory>

using std::tr1::shared_ptr;

struct node {
shared_ptr<node> next;
};

int main() {


shared_ptr<node> root(new node);
shared_ptr<node> n(root);

for (int x = 0; x < 1000000; ++x) {


n = n->next = shared_ptr<node>(new node);
}
}

When the "root" shared_ptr goes out of scope, the first node's reference
count goes to zero. root's destructor therefore deletes the first node,
causing the destructor of root->next to be invoked. That destructor
sees the reference count of the second node become zero, and so deletes
the second node, causing root->next->next to be invoked. And so on...

A better approach, IMHO, would be to let a factory allocate the nodes,
preferably as elements of a std::list<node>. The factory's destructor
(the list's, really) can make sure the memory is freed.

Alf P. Steinbach

unread,
Feb 29, 2008, 12:34:59 AM2/29/08
to
* Jeff Schwab:

Thanks. I didn't see that. Blind on both eyes! :-)

> A better approach, IMHO, would be to let a factory allocate the nodes,
> preferably as elements of a std::list<node>. The factory's destructor
> (the list's, really) can make sure the memory is freed.

Yup.

James Kanze

unread,
Feb 29, 2008, 4:50:45 AM2/29/08