Get it at:
http://sourceforge.net/projects/sgcl/
Regards
Sebastian Nibisz
If you need garbage collection you should try D language.
> 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.
> Get it at:
> http://sourceforge.net/projects/sgcl/
--
When the PC was launched, people knew it was important.
-- Bill Gates
The D language doesn't have the parallel garbage collector.
Regards
Sebastian Nibisz
Garbage collection is for lazy rich folks who can't be bothered to
take out their own trash.
It's funny.
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?
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...
A recursive function?
--
Erik Wikström
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.
> > 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
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
{
for (int x = 0; x < 1000000; ++x)
{
n = n->next = shared_ptr<node>(new node);
}
} // <- STACK OVERFLOW
rgds
Sebastian Nibisz
Stack overflow?
--
Thomas
http://www.netmeister.org/news/learn2quote.html
To iterate is human, to recurse divine.
-L. Peter Deutsch
Why?
It's hard to guess why you would allocate nodes that way in the first place.
{
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
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;
The parent must know the child.
rgds
Sebastian Nibisz
> 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.
> > 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).
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.
Sounds like interesting stuff for anyone who wants to use GC in his/her
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?
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.
>> 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.
> 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.
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.
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.
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.