Topic: Notes on garbage collection, reference counting, and manual storage allocation


Author: dcrocker@eschertech.ccoomm ("David Crocker")
Date: Tue, 14 Dec 2004 23:20:12 GMT
Raw View
""Thorsten Ottosen"" <nesotto@cs.auc.dk> wrote in message
news:41bde26b$0$74685$14726298@news.sunsite.dk...
>
> "Larry Evans" <cppljevans@cox-internet.com> wrote in message
> news:10rimon7uk31fbd@corp.supernews.com...
> | On 12/09/2004 10:24 PM, Thorsten Ottosen wrote:
> | [snip]
> | >
> | > yes, we really need to support optional garbage collection.
> | >
> | > | Regretfully, there are a few things in the current standard that
would
> | > | make it non conforming.
> | >
> | > If I understand the situation correctly, then present day C++ garbage
> | > collectors
> | > cannot remove circular references. If that is true, then we should
> consider
> | I assume you mean precise collectors, because the Boehm conservative
> | can certainly handle cycles in the pointer graph.
>
>
> Actually I said that because I thought I read that the boehm collector
could
> not detect
> cycles. Please refer to
>
> http://hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc_cpph.txt

The problem arises only if you declare cleanup functions for both objects. I
think it is unlikely that you would want to do that.

The real problem with GC in a language like C++ is destructors, since the
destructor is called when the object is collected, which may be some time
after it becomes inaccessible. Although destructors are most often used to
free up sub-objects (and hence are unnecessary if GC is being used), they
can also be used to close windows, file handles, sockets etc. when the
object that represents them is finished with. Java's solution is the
"finally" clause, providing a way of performing this sort of finalisation
when an object goes out of scope. If C++ gets optional GC (and I hope it
does), I think it will need something like a "finally" clause too.

David Crocker
www.eschertech.com




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Hans Boehm" <Hans_Boehm@hp.com>
Date: Tue, 14 Dec 2004 18:54:59 CST
Raw View
John Nagle wrote:

> 2) remains a tough
> problem for a language with destructors, like C++.
> Destructors are called long after the object is
> no longer needed, so if they're supposed to release
> some resource like a window or a socket, the resource
> is released late, if ever.  Destructors may be called
> by an unexpected thread at an unexpected time, so they
> have to have locking.  Such locking may deadlock the
> garbage collector.
>
I would argue that's backwards.  Destructors triggered by reference
counting may be called by an unexpected thread at an unexpected time.
An assignment somewhere in your may recursively cause deletion of and
destructor invocations on objects that should be opaque to you.  The
destructor may access a global data structure (e.g. to remove the
object from a table) which is currently being accessed by one of your
callers, and is hence locked leading to self-deadlock (bad) or in an
inconsistent state (worse).

Garbage-collector triggered finalizers are normally enqueued during GC
and then run asynchronously in their own thread(s).  It is perfectly
safe for them to lock, as they should.  (Our GC does something else by
default, mostly for historical reasons, and because it can't rely on
the presence of threads.  That works only for trivial uses.  Anything
at all sophisticated should avoid the default.  I think all major Java
and .Net implementations now do this correctly.)

For details see http://portal.acm.org/citation.cfm?doid=604131.604153
or http://www.hpl.hp.com/techreports/2002/HPL-2002-335.html .

Hans

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Hans Boehm" <Hans_Boehm@hp.com>
Date: Tue, 14 Dec 2004 19:47:40 CST
Raw View
John Nagle wrote:

> 2) remains a tough
> problem for a language with destructors, like C++.
> Destructors are called long after the object is
> no longer needed, so if they're supposed to release
> some resource like a window or a socket, the resource
> is released late, if ever.  Destructors may be called
> by an unexpected thread at an unexpected time, so they
> have to have locking.  Such locking may deadlock the
> garbage collector.
>
I would argue that's backwards.  Destructors triggered by reference
counting may be called by an unexpected thread at an unexpected time.
An assignment somewhere in your may recursively cause deletion of and
destructor invocations on objects that should be opaque to you.  The
destructor may access a global data structure (e.g. to remove the
object from a table) which is currently being accessed by one of your
callers, and is hence locked leading to self-deadlock (bad) or in an
inconsistent state (worse).

Garbage-collector triggered finalizers are normally enqueued during GC
and then run asynchronously in their own thread(s).  It is perfectly
safe for them to lock, as they should.  (Our GC does something else by
default, mostly for historical reasons, and because it can't rely on
the presence of threads.  That works only for trivial uses.  Anything
at all sophisticated should avoid the default.  I think all major Java
and .Net implementations now do this correctly.)

For details see http://portal.acm.org/citation.cfm?doid=604131.604153
or http://www.hpl.hp.com/techreports/2002/HPL-2002-335.html .

Hans

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Wed, 15 Dec 2004 15:05:13 CST
Raw View
"David Crocker" wrote:
> ""Thorsten Ottosen"" <nesotto@cs.auc.dk> wrote in message
> news:41bde26b$0$74685$14726298@news.sunsite.dk...

> > "Larry Evans" <cppljevans@cox-internet.com> wrote in message
> > news:10rimon7uk31fbd@corp.supernews.com...
> > | On 12/09/2004 10:24 PM, Thorsten Ottosen wrote:
> > | [snip]

> > | > yes, we really need to support optional garbage collection.

> > | > | Regretfully, there are a few things in the current standard
> > | > | that would make it non conforming.

> > | > If I understand the situation correctly, then present day C++
> > | > garbage collectors cannot remove circular references. If that
is
> > | > true, then we should > consider > > | I assume you mean precise
> > | > collectors, because the Boehm conservative > > | can certainly
> > | > handle cycles in the pointer graph.

> > Actually I said that because I thought I read that the boehm
> > collector could not detect cycles. Please refer to

> > http://hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc_cpph.txt

> The problem arises only if you declare cleanup functions for both
> objects. I think it is unlikely that you would want to do that.

> The real problem with GC in a language like C++ is destructors, since
> the destructor is called when the object is collected, which may be
> some time after it becomes inaccessible.

The real problem is that people confuse destruction and finalization.
As it currently stands, Java doesn't have destructors, and C++ folds
destruction and finalization into one operation.

Garbage collection or no, you still need deterministic destruction for
some objects.  (In Java, you use special programming conventions, with
a
specified function called in a finally block.)  I presume that even
with
garbage collection, destructors in C++ will continue to work as they
always have.

> Although destructors are most often used to free up sub-objects (and
> hence are unnecessary if GC is being used), they can also be used to
> close windows, file handles, sockets etc. when the object that
> represents them is finished with.

You have to be very careful with this sort of thing.  You should not
call a function that may fail in a destructor, unless you can
absolutely
ignore the failure.  Closing a file open for writing, for example, is
only acceptable if you intend to immediately delete the file without
ever reading it.

> Java's solution is the "finally" clause, providing a way of
performing
> this sort of finalisation when an object goes out of scope. If C++
> gets optional GC (and I hope it does), I think it will need something
> like a "finally" clause too.

Why?  GC won't affect local objects, so the same RAII pattern that is
current today will continue to work.

--
James Kanze           GABI Software         http://www.gabi-soft.fr
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


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Hans Boehm" <Hans_Boehm@hp.com>
Date: Thu, 16 Dec 2004 12:05:13 CST
Raw View
John Nagle wrote:
> Hans Boehm wrote:
> > I would argue that's backwards.  Destructors triggered by reference
> > counting may be called by an unexpected thread at an unexpected
time.
> > An assignment somewhere in your may (?) recursively cause deletion
of and
> > destructor invocations on objects that should be opaque to you.
The
> > destructor may access a global data structure (e.g. to remove the
> > object from a table) which is currently being accessed by one of
your
> > callers, and is hence locked leading to self-deadlock (bad) or in
an
> > inconsistent state (worse).
>
>     A program vulnerable to that problem from reference counting is
> also vulnerable to it from garbage collection.  But in a system
> that runs garbage collection at random times, the problem will
> generate unrepeatable race conditions.
Finalizers triggered by a GC need to lock global data structures they
access.  Since they are run in their own thread, and can thus safely
block, they are essentially a form of concurrency and require threads.
But it is just as easy or difficult to avoid deadlock with (properly
implemented) finalizers as it is with any other form of concurrency.

If a classic reference count system synchronously invokes destructors,
then you can get the kind of deadlock I described above.  That can be
avoided by enqueuing them explicitly and running them in a separate
thread.  But then they don't behave that differently from GC-based
finalizers.  They are no longer synchronous, and don't occur at a
deterministic program point.

I agree with everything else in John's posting.  Synchronous
(deterministic) destruction is very different from asynchronous
finalization.  They usually serve different purposes.  There are
arguments for and against reusing the same syntax.  But the programmer
certainly needs to be aware of the distinction.

Hans

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Hans Boehm" <Hans_Boehm@hp.com>
Date: Fri, 17 Dec 2004 18:00:53 CST
Raw View
John Nagle wrote:
> Hans Boehm wrote:
>
> > John Nagle wrote:
> >
> >>Hans Boehm wrote:
>
> > Finalizers triggered by a GC need to lock global data structures
they
> > access.  Since they are run in their own thread, and can thus
safely
> > block, they are essentially a form of concurrency and require
threads.
> > But it is just as easy or difficult to avoid deadlock with
(properly
> > implemented) finalizers as it is with any other form of
concurrency.
>
>     True.
>
>     There's something to be said for a highly concurrent style of
> programming, where there are free-running threads all over the
> place and everything is locked when necessary.
>
>     But that's an uncommon style for C++.  It's much more common
> for C++ code to assume purely sequential execution and not lock much.
> The language, after all, provides no support for threads or locking.
>
I think that's likely to change quickly in many domains, as the average
desktop becomes a multiprocessor, and single-threaded code is no longer
performance-competitive.  (With "Hyperthreaded" Pentium 4s and the
like, we're almost there already, but perhaps not quite.)

Even more importantly, this problem occurs just as easily without
threads.

Code that synchronously and unexpectedly runs a finalizer accessing
global data structure A as a result of a reference-counted assignment
inside one of A's methods is broken, whether there are threads and
locks or not.  The case of non-reentrant locks is cleanest, in that you
are guaranteed to get a deadlock, and the problem is likely to be
easily isolated.  In the sequential case, the finalizer just runs on an
inconsistent version of A, and you will either get lucky and things
will happen to work, or you get silent data corruption.  With reentrant
locks, as in Java, you get behavior similar to the single-threaded
case, except that more complicated deadlocks are also possible.

You need threads and locks as part of the solution; they are not the
problem.

And I don't know of a clean way to prevent the introduction of code
like the above in a reference counted system with synchronous
finalization.  You need to violate all sorts of abstraction boundaries
in order to tell whether something like this might happen.

If you can find old Sun Java bug reports, you can get a good idea of
what happens when you do this on a large scale.  Very old Sun JVMs used
to run finalizers from the garbage collector, so that they could be run
synchronously at any allocation call.  That's arguably better than
being able to run it from any pointer assignment, as with reference
counting.  But it was bad enough for the HotJava browser to crash with
annoying regularity on the platform I was working on at the time.
(Many other JVMs later made the same mistake, though the language spec
never allowed this.  At this point, I think they've all been fixed
years ago.)

John is right that finalizers don't fit very well into single-threaded
programs.  You end up with an explicit API call to invoke pending
finalizers, and the client has to remember to call it occasionally.
This is clearly not elegant.  As I argued above, it's likely to be a
temporary problem, though.

Hans

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: skaller@nospam.com.au ("John Max Skaller")
Date: Tue, 21 Dec 2004 04:33:50 GMT
Raw View
On Fri, 10 Dec 2004 05:24:52 +0000, Thorsten Ottosen wrote:

> yes, we really need to support optional garbage collection.

If you really want to mix GC with destructors, you will
need something like Felix

http://felix.sf.net

Optional collection (in the sense of a global choice)
isn't viable. Mandatory collection is certainly viable
and readily available -- just configure the Boehm-Reiser
collector and forget about memory management in new
code.

In theory the Felix collector is much faster,
since it is an exact collector, and it only
collects large objects. However it requires
thought to use when interfacing with C++,
which the Boehm collector does not.

If you really want fast automatic memory management
and high power programming, use a more advanced
language than C++ such as Ocaml, Clean, or Haskell.
Of course the price is loss of compatibility.

Again, if you want fast code, semi-automatic memory
management, and semi-transparent integration with
C++ -- try Felix. It is specifically
designed as a compromise between advanced systems
and compatibility with legacy C++ applications.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "John Max Skaller" <skaller@nospam.com.au>
Date: Mon, 20 Dec 2004 22:37:04 CST
Raw View
On Wed, 15 Dec 2004 15:05:27 -0600, John Nagle wrote:

>     But we can't ignore the problem any more.  It's starting
> to attract attention at the higher levels of the Department
> of Homeland Security.  See Amit Yoran's speech on the
> "19 programming flaws" that cause most security vulnerabilities.

I don't understand this comment. You can ignore the problem,
if you want a secure application just don't use C++.

It was designed from the start to place C compatibility
ahead of being a good programming language. There are times
when that compromise is uncomfortable, and then
you have to choose whether to go with a high level language
or a backward compatible one.

It's just unfortunate many people have chosen to
go with a language which is neither C compatible,
fast, portable, OR high level, when, once you're
ready to give up on compatibility there are
superior languages around.

Originally, C++ did offer something else fairly unique:
high performance. That is no longer the case. Even scripting
language like Python compare favourably with C++ for many
applications now (due to changed CPU architectures).

So I really don't understand 'we can't ignore the
problem anymore'. It is not as if the issue wasn't
understood and considered before, and quite some time
before. Perhaps needs are changing -- but that implies
choosing a system that isn't committed to C compatibility --
destructors vs. garbage collection isn't really the issue.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Mon, 20 Dec 2004 22:35:16 CST
Raw View
John Nagle wrote:
> Hans Boehm wrote:

> > John Nagle wrote:

> >>Hans Boehm wrote: > Finalizers triggered by a GC need to lock
global
> data structures they > access.  Since they are run in their own
> thread, and can thus safely > block, they are essentially a form of
> concurrency and require threads.  > But it is just as easy or
> difficult to avoid deadlock with (properly > implemented) finalizers
> as it is with any other form of concurrency.

>     True.

>     There's something to be said for a highly concurrent style of
> programming, where there are free-running threads all over the place
> and everything is locked when necessary.

Sounds like a recepe for disaster:-).

>     But that's an uncommon style for C++.  It's much more common for
> C++ code to assume purely sequential execution and not lock much.
The
> language, after all, provides no support for threads or locking.

Perhaps, but I've never seen any C++ code which used only what was
provided by the standard.

>     In particular, seldom is C++ GUI code written for a highly
> concurrent model.  Arguably, it should be, but for historical
reasons,
> most GUI systems are single-thread.  Threads came late to both UNIX
> and Windows, and we still feel the weight of the problems created by
> that.

They may have come late, but they have come, and I don't know of any
server or GUI software for either platform which isn't multithreaded.
In fact, I'd say that the tendancy has gone too much to the opposite
extreme, and many applications are ignoring the alternatives of
single-threaded or multi-process.

>      Java has a different history and different conventions.  The
> garbage collection/finalizer model works well for Java.  But what
> works for Java is tough to retrofit to C++.

The choice between destructor and finalizer has in the end very little
to do with the language.  Arguably, you need both, and a language which
provides only one is missing something.  (In the case of C++ today, the
two fuse because destructors also take care of "garbage collection".)

--
James Kanze           GABI Software         http://www.gabi-soft.fr
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


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: swelef@post.sk
Date: Tue, 21 Dec 2004 11:59:08 CST
Raw View
John Max Skaller wrote:
> On Wed, 15 Dec 2004 15:05:27 -0600, John Nagle wrote:
[snip]
> It's just unfortunate many people have chosen to
> go with a language which is neither C compatible,
> fast, portable, OR high level, when, once you're
> ready to give up on compatibility there are
> superior languages around.
[snip]

Except for the lack of threading and garbage collection
in the standard I find C++ superior to all other languages.
Given the fact that C++/CLI will _somehow_ (not to my liking)
fix these issues while preserving the full power of C++ we
will have a language that will be _strictly_ superior to all
other languages I know. I mean I don't know any programming
style that C++/CLI would not support.

Regards,
Vladimir Marko

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "John Max Skaller" <skaller@nospam.com.au>
Date: Wed, 22 Dec 2004 12:10:00 CST
Raw View
3g2000cwb.googlegroups.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
Path:
NNTP-Posting-Host: ppp194-89.lns1.syd2.internode.on.net
X-Trace: duster.adelaide.on.net 1103681866 203.122.194.89 (22 Dec 2004 12:47:46 +1050)
Lines: 54

On Tue, 21 Dec 2004 11:59:08 -0600, swele wrote:

> John Max Skaller wrote:
>> On Wed, 15 Dec 2004 15:05:27 -0600, John Nagle wrote:
> [snip]
>> It's just unfortunate many people have chosen to
>> go with a language which is neither C compatible,
>> fast, portable, OR high level, when, once you're
>> ready to give up on compatibility there are
>> superior languages around.
> [snip]
>
> Except for the lack of threading and garbage collection
> in the standard I find C++ superior to all other languages.

However implicit in this assertion is that this is your
experience, and hence restricted to the languages you've
actually considered.

You may find it instructive to consider languages such as
Ocaml and Haskell, which are truly more advanced than C++.

> Given the fact that C++/CLI will _somehow_ (not to my liking)
> fix these issues while preserving the full power of C++

Seems unlikely MS will fix anything, they're not well known
for placing good design ahead of marketting.

> we
> will have a language that will be _strictly_ superior to all
> other languages I know. I mean I don't know any programming
> style that C++/CLI would not support.

The one almost all academics, and an increasing number of
discerning industrial progammers favour -- functional programming.

It used to be FP languages were slow. This is no longer the
case: they're typically easier to develop and run as fast
if not faster than C++, and are unquestionably cheaper in
terms of maintenance.

There are two major obstacles to the adoption of these systems, IMHO:

(A) lack of education
(B) difficulty of interfacing with C/C++

Felix attempts to solve problem (B), by making C/C++
interfacing a central theme of the system, whilst providing
most of the significant advantages of functional programming.

It also makes some steps to helping with (A), by providing
an industrial bridge between C++ and a more functional
programming style.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pjp@plauger.com
Date: Tue, 7 Dec 2004 15:13:32 CST
Raw View
===================================== MODERATOR'S COMMENT:
 Please use a non-bizarre quoting convention in future posts.  Thanks.


===================================== END OF MODERATOR'S COMMENT
In the languages with manual storage allocation (C, C++,
Pascal, etc.) programmers must obsess on storage management.
It dominates program design and is a constant source of bugs.

[pjp] Doesn't dominate my design. I use a few proven and safe idioms
for storage allocation to minimize bugs. I do the same with
multithreading, which is an ever greater source of potential problems,
copying nul-terminated strings, looping over floating-point values,
etc. etc. And I bet I'm not alone in this approach to professional
programming.

In languages with safe garbage collection (LISP, Java), garbage
collection requires some programmer attention. Speed,
concurrency, stalls, virtual memory thrashing,
and finalizer semantics all require attention. Side effects
of finalizers are especially troublesome.

[pjp] Yep, which is why I don't use finalizers. All them other things
are just part of the attention you give to writing any robust piece of
software.

In languages with safe reference counts (Perl, Python, Visual
Basic), programmers seem to barely be aware of storage
management. Even finalization tends to be a non-problem.
Visual Basic destroys GUI widgets during finalization,
yet this doesn't seem to require much programmer
attention.

[pjp] Funny, I find that I have to devote about the same amount of
careful attention to such issues no matter how hard the underlying
language endeavors to protect me from myself (and/or writing efficient
code). YMMV, of course.

This bears thinking about.

[pjp] Now that you've drawn our attention to it, I'm sure that some
people will finally get around to considering the tradeoffs.
P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: tom.horsley@att.net (Thomas A. Horsley)
Date: Wed, 8 Dec 2004 22:47:39 GMT
Raw View
Just out of curiosity, why is it that "reference counting" seems to be
classified as an utterly separate and distinct concept from "garbage
collection"?

There are umpteen gazillion garbage collection algorithms around, in what
way is "reference counting" so unique that it always seems to be called out
as a separate entity in these discussions rather than merely being
classified as one of the other gazillion garbage collection algorithms?

(And anyone who thinks reference counting is transparent and problem free in
perl should go search the perl5-porters mailing list archives for
discussions on destructors and order of destruction problems :-).
--
>>==>> The *Best* political site <URL:http://www.vote-smart.org/> >>==+
      email: Tom.Horsley@worldnet.att.net icbm: Delray Beach, FL      |
<URL:http://home.att.net/~Tom.Horsley> Free Software and Politics <<==+

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: sjhoweATdialDOTpipexDOTcom@eu.uu.net ("Stephen Howe")
Date: Thu, 9 Dec 2004 05:30:17 GMT
Raw View
>    This bears thinking about.

Not really. It has been threshed here and c.l.c++.m time and time again.
Your not saying anything new.

What will _never_ happen, is that C++ gains mandatory garbage collection.
Many of GC proponents don't get that.
They think that if they keep re-presenting their arguments, the non-GC
proponents will eventually be won over.
Not a chance. There is no way that old working C++ code would be abandoned.

What _might_ happen, is that C++ could gain optional garbage collection.
That is if you choose not to use it, you have C++ programs like you have
now.
Most C++ programmers I think could accept optional garbage collection (with
no mission creep).
D has optional garabage collection.
But it won't happen until someone does some serious work and present a paper
to the C++ committee.
Until then, it is hot air.

Stephen Howe






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: alfps@start.no (Alf P. Steinbach)
Date: Thu, 9 Dec 2004 10:04:01 GMT
Raw View
* Thomas A. Horsley:
>
> Just out of curiosity, why is it that "reference counting" seems to be
> classified as an utterly separate and distinct concept from "garbage
> collection"?

Ah, nothing like jumping into the middle of a thread without finding
the rest of it (and I'm too lazy)!

Reference counting is special because it yields the possibility of
deterministic _destruction_, invocation of a destructor.

Which is different from memory reclamation (after destruction memory
reclamation can follow at any time; immediately, or performed later
on by a non-ref-counting garbage collector, which might be more
efficient than doing it piecemeal at the time of object destruction).

Not that I think it would be a good idea to add reference counting
to C++.

On the other hand, I aired an idea in clc++m where the destruction
bit works just like now, but memory reclamation is delegated to a
garbage collector; i.e., operator delete just informs an asynchronous
garbage collector that the memory can now be reclaimed.  It seems
there is nothing in the standard that prohibits that.  At least
nobody then mentioned such obstacles.

However, I think it was James Kanze who pointed that out, most C++
destructors deal with nothing _but_ deallocation, and so in such a
C++ implementation one would have lots of what in a fully garbage-
collection based language would be unnecessary destructor code and
destructor calls.

One can't have everything: the point of the idea is not to avoid
"trivial" destructors, or change the language syntax or semantics in
any way whatsoever, but just to possibly optimize memory reclamation.

I'm not sure what the performance gain (or loss) of this idea would
be, or whether it's ever been implemented, or whether there just
might be some subtle wording in the standard that prohibits it  --
does anyone know or have thoughts?

--
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?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Thu, 9 Dec 2004 11:58:12 CST
Raw View
Alf P. Steinbach wrote:
> * Thomas A. Horsley:

> > Just out of curiosity, why is it that "reference counting" seems to
> > be classified as an utterly separate and distinct concept from
> > "garbage collection"?

> Ah, nothing like jumping into the middle of a thread without finding
> the rest of it (and I'm too lazy)!

> Reference counting is special because it yields the possibility of
> deterministic _destruction_, invocation of a destructor.

One problem we have is that reference counting seems to mean two
different things.  One of those is reference counting, and the other is
a variant of garbage collection which uses reference counting.
Reference counting can be used for a multitude of things: I've got
examples where it is used to manage mutex locks, and examples where it
is used to control when an output buffer must be flushed.  In both
cases, I'd be using reference counting even in Java (with the
difference
that in Java, I'd probably need a few finally blocks to ensure that the
reference count gets correctly decremented).

> Which is different from memory reclamation (after destruction memory
> reclamation can follow at any time; immediately, or performed later
on
> by a non-ref-counting garbage collector, which might be more
efficient
> than doing it piecemeal at the time of object destruction).

> Not that I think it would be a good idea to add reference counting to
> C++.

Agreed.  You can't put everything that might occasionally be useful in
the library.

> On the other hand, I aired an idea in clc++m where the destruction
bit
> works just like now, but memory reclamation is delegated to a garbage
> collector; i.e., operator delete just informs an asynchronous garbage
> collector that the memory can now be reclaimed.  It seems there is
> nothing in the standard that prohibits that.  At least nobody then
> mentioned such obstacles.

I missed the suggestion.  I like it a lot.

Regretfully, there are a few things in the current standard that would
make it non conforming.  Code like the following, for example:

C*            pC = new C ;
unsigned char buf[ sizeof( C* ) ] ;
memcpy( buf, &pC, sizeof( C* ) ) ;
pC = NULL ;
encrypt( buf ) ;
//  ...
decrypt( buf ) ;
memcpy( &pC, buf, sizeof( C* ) ) ;
pC-> ...

I doubt that such code is wide spread.  I know that I've never written
anything of the sort, but I have no idea whether there are programs
which legitimately do so.  (Note that in another variant, encrypt and
decrypt are named writeToDisk and readFromDisk, or
registerWithCentralServer, and getFromRegistry, or ...  One could
almost
imagine something like the latter actually occuring in some distributed
architecture, say Corba based.)

--
James Kanze           GABI Software         http://www.gabi-soft.fr
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


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nesotto@cs.auc.dk ("Thorsten Ottosen")
Date: Fri, 10 Dec 2004 05:24:52 GMT
Raw View
<kanze@gabi-soft.fr> wrote in message
news:1102597448.421848.172730@c13g2000cwb.googlegroups.com...
| Alf P. Steinbach wrote:

| > On the other hand, I aired an idea in clc++m where the destruction
| bit
| > works just like now, but memory reclamation is delegated to a garbage
| > collector; i.e., operator delete just informs an asynchronous garbage
| > collector that the memory can now be reclaimed.  It seems there is
| > nothing in the standard that prohibits that.  At least nobody then
| > mentioned such obstacles.
|
| I missed the suggestion.  I like it a lot.

yes, we really need to support optional garbage collection.

| Regretfully, there are a few things in the current standard that would
| make it non conforming.

If I understand the situation correctly, then present day C++ garbage
collectors
cannot remove circular references. If that is true, then we should consider
adding
some kind of strict mode which allows garbage collection to work without
problems.

-Thorsten



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: alfps@start.no (Alf P. Steinbach)
Date: Fri, 10 Dec 2004 08:02:34 GMT
Raw View
* kanze@gabi-soft.fr:
>
> > On the other hand, I aired an idea in clc++m where the destruction
> bit
> > works just like now, but memory reclamation is delegated to a garbage
> > collector; i.e., operator delete just informs an asynchronous garbage
> > collector that the memory can now be reclaimed.  It seems there is
> > nothing in the standard that prohibits that.  At least nobody then
> > mentioned such obstacles.
>
> I missed the suggestion.  I like it a lot.
>
> Regretfully, there are a few things in the current standard that would
> make it non conforming.  Code like the following, for example:
>
> C*            pC = new C ;
> unsigned char buf[ sizeof( C* ) ] ;
> memcpy( buf, &pC, sizeof( C* ) ) ;
> pC = NULL ;
> encrypt( buf ) ;
> //  ...
> decrypt( buf ) ;
> memcpy( &pC, buf, sizeof( C* ) ) ;
> pC-> ...

I don't understand how that is an example where operator-delete-
initiated garbage collection wouldn't work.

Probably I was unclear in my description.

Such a garbage collector would have no business going around inspecting
pointers to check if they're valid.  It would merely have the task
of reclaiming memory marked for reclamation by operator delete.
As soon as the above piece of code calls operator delete, then the
garbage collector can kick in at any time, including immediately.

Or, I misunderstood the example.

Or, I understood it correctly but didn't understand the significance.

--
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?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Fri, 10 Dec 2004 12:32:53 CST
Raw View
Alf P. Steinbach wrote:
> * kanze@gabi-soft.fr:

> > > On the other hand, I aired an idea in clc++m where the
destruction
> > > bit works just like now, but memory reclamation is delegated to a
> > > garbage collector; i.e., operator delete just informs an
> > > asynchronous garbage collector that the memory can now be
> > > reclaimed.  It seems there is nothing in the standard that
> > > prohibits that.  At least nobody then mentioned such obstacles.

> > I missed the suggestion.  I like it a lot.

> > Regretfully, there are a few things in the current standard that
would
> > make it non conforming.  Code like the following, for example:

> > C*            pC = new C ;
> > unsigned char buf[ sizeof( C* ) ] ;
> > memcpy( buf, &pC, sizeof( C* ) ) ;
> > pC = NULL ;
> > encrypt( buf ) ;
> > //  ...
> > decrypt( buf ) ;
> > memcpy( &pC, buf, sizeof( C* ) ) ;
> > pC-> ...

> I don't understand how that is an example where operator-delete-
> initiated garbage collection wouldn't work.

> Probably I was unclear in my description.

> Such a garbage collector would have no business going around
> inspecting pointers to check if they're valid.  It would merely have
> the task of reclaiming memory marked for reclamation by operator
> delete.  As soon as the above piece of code calls operator delete,
> then the garbage collector can kick in at any time, including
> immediately.

OK.  I misunderstood the suggestion.

If all that is being suggested is that memory released by delete is not
necessarily immediately available for new, that is the current
situation.  Formally speaking, ::operator delete( void* ){} is a fully
conforming implementation.

I just don't see any interest; as a programmer, I still have to call
delete on every object.  The advantage of garbage collection, as I see
it, is that I don't need any of the destructors which do nothing but
free memory.

--
James Kanze           GABI Software         http://www.gabi-soft.fr
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


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gianluca_silvestri75@yahoo.it ("Gianluca Silvestri")
Date: Fri, 10 Dec 2004 21:45:33 GMT
Raw View
""Stephen Howe"" <sjhoweATdialDOTpipexDOTcom@eu.uu.net> ha scritto nel
messaggio news:41b7dd3c$0$3137$cc9e4d1f@news.dial.pipex.com...
>>    This bears thinking about.

> What _might_ happen, is that C++ could gain optional garbage collection.
> That is if you choose not to use it, you have C++ programs like you have
> now.
> Most C++ programmers I think could accept optional garbage collection
> (with no mission creep).
> D has optional garabage collection.
> But it won't happen until someone does some serious work and present a
> paper to the C++ committee.
 Couldn't that proposal be that of C++/CLI, or at least the general ideas
and syntax?
What do you think?

Gianluca Silvestri


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Fri, 10 Dec 2004 15:47:53 CST
Raw View
"Thorsten Ottosen" wrote:
> <kanze@gabi-soft.fr> wrote in message
> news:1102597448.421848.172730@c13g2000cwb.googlegroups.com...

> | Regretfully, there are a few things in the current standard that
would
> | make it non conforming.

> If I understand the situation correctly, then present day C++ garbage
> collectors cannot remove circular references.

The problem has nothing to do with circular references.  The problem is
that the C++ standard currently allows "hiding" a pointer in ways that
a
garbage collector cannot possibly find it.  And when the garbage
collector cannot find any pointers to an object, it collects the
object.  If the code then later recovers the pointer, and dereferences
it, there is a problem.

> If that is true, then we should consider adding some kind of strict
> mode which allows garbage collection to work without problems.

Agreed.  Basically, I think that 1) garbage collection must be
optional,
and 2) if it is used, a limited number of things which are currently
legal become undefined behavior.

--
James Kanze           GABI Software         http://www.gabi-soft.fr
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


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nesotto@cs.auc.dk ("Thorsten Ottosen")
Date: Mon, 13 Dec 2004 19:06:23 GMT
Raw View
"Larry Evans" <cppljevans@cox-internet.com> wrote in message
news:10rimon7uk31fbd@corp.supernews.com...
| On 12/09/2004 10:24 PM, Thorsten Ottosen wrote:
| [snip]
| >
| > yes, we really need to support optional garbage collection.
| >
| > | Regretfully, there are a few things in the current standard that would
| > | make it non conforming.
| >
| > If I understand the situation correctly, then present day C++ garbage
| > collectors
| > cannot remove circular references. If that is true, then we should
consider
| I assume you mean precise collectors, because the Boehm conservative
| can certainly handle cycles in the pointer graph.


Actually I said that because I thought I read that the boehm collector could
not detect
cycles. Please refer to

http://hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc_cpph.txt

and in partcular this paragraph:

"Thus, if objects A and B both have clean-up functions, and A points at
B, B is considered accessible.  After A's clean-up is invoked and its
storage released, B will then become inaccessible and will have its
clean-up invoked.  If A points at B and B points to A, forming a
cycle, then that's considered a storage leak, and neither will be
collectable.  See the interface gc.h for low-level facilities for
handling such cycles of objects with clean-up.

The collector cannot guarrantee that it will find all inaccessible
objects.  In practice, it finds almost all of them."

-Thorsten


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Hans Boehm" <Hans_Boehm@hp.com>
Date: Mon, 13 Dec 2004 13:07:52 CST
Raw View
John Nagle wrote:
>     The major reason circular structures aren't a major problem
> is that, unlike dangling pointers, they rarely happen by
> accident.   Either they're designed into a data structure,
> in which case you tend to get memory leaks which show up early
> in debugging, or they don't happen at all.  So they tend not
> to result in subtle defects or intermittent failures.
>
There are certainly counter-examples to this.  Generic "property lists"
hanging off an object A are one way to get unexpected cycles.  You
don't get a cycle until you add an object to the property list that
happens to refer back to A, which may happen quite rarely.

Chained hash tables also tend to give rise to occasional cycles if the
objects in the table have other links between them, and if the hash
links are embedded inthe objects themselves, as is often the case.  So
long as there are no hash collisions, there are no hash chains, and
hence no cycles.  Once the table fills up, you start getting cycles.

In general, I think the problem is not with a single "data structure".
The unexpected cycles occur when you superimpose several data
structures.

I think you either have to handle cycles correctly and automatically
or, at a minimum, you have to provide a tool for detecting cycles
during testing.

(There are reference count collectors that not only perform cycle
detection, but perform competitively in the presence of threads.  See
for example the work by Bacon et al. or Levanoni and Petrank.  There
are references and more relevant discussion in:  Boehm, "The Space Cost
of Lazy Reference Counting", POPL 2004,
http://portal.acm.org/citation.cfm?doid=1011767.1011774, or
http://www.hpl.hp.com/techreports/2003/HPL-2003-215.html.)

Hans

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]