Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

New C++ garbage collector

103 views
Skip to first unread message

Matthias Meixner

unread,
Oct 25, 2010, 5:20:56 PM10/25/10
to

Just in case you are interested, there is a new garbage collector for C++:

http://sourceforge.net/projects/meixnergc/

So what does it do what others cannot do? Here is the list:

- It is not a conservative garbage collector like e.g. the Boehm
collector. Therefore, all garbage will eventually be cleaned

- Due to using mark and sweep it has no problems with cyclic data
structures (no reference counting).

- It uses incremental garbage collection to smoothly spread the workload
of the garbage collector over the whole runtime

- By using a non-intrusive design it allows to handle all kind of
data/objects.

- It provides a universal smart pointer that can be used to point to
anything, single objects and arrays (no different smart pointer types
for objects and arrays). It may also safely be used to point to data on
stack or global data.

- It simulates the normal automatic pointer type conversion, e.g.
gc_ptr<A> will be automatically casted to gc_ptr<B> if A is a subclass of B.

Currently it is designed to be used with gcc / pthreads. The
single-threading version should be usable with any C++ compiler. The
multi-threading version should work with any platform that supports
POSIX threads.

So what do you think?

- Matthias Meixner

debra h

unread,
Oct 26, 2010, 4:14:46 AM10/26/10
to

The collector is also used by a number of programming language
implementations that either use C as intermediate code, want to
facilitate easier interoperation with C libraries, or just prefer the
simple collector interface. For a more detailed description of the
interface, see here: http://www.hpl.hp.com/personal/Hans_Boehm/gc/

SG

unread,
Oct 26, 2010, 4:35:55 AM10/26/10
to
On 25 Okt., 23:20, Matthias Meixner wrote:
>
> Just in case you are interested, there is a new garbage collector for C++:
> http://sourceforge.net/projects/meixnergc/
>
> [...]

The bullet points you list don't really explain much. Your README is
much more informative. Maybe, you should consider putting this README
(or some equivalent documetation) somewhere easy to find so people
don't have to download the source code first.

It seems like an interesting concept. Your GC is even trying to invoke
destructors, though, I would feel uneasy about this in a multi-
threaded application. When and where does garbage collection actually
take place? It sounds like you're performing "little garbage
collection steps" during each invocation of your overloaded new
operator instead of, say, using a separate GC thread. Anyhow, it must
be hard to get it right in a multi-threaded application. I wouldn't be
surprized if there are a couple of problems/bugs left. BTW: I just
skimmed over the source code and wondered why you felt the need to
explicitly disable inlining for a couple functions. Usually, when
people observe that their programs break after turning on compiler
optimizations, it's due to undefined behaviour... ;-)

I generelly don't feel the need to use/test any garbage collectors for
C or C++. I guess the kind of applications I deal with mostly --
number chrunching -- simply doesn't call for garbage collection. I get
along very well without it. That's not to say the topic isn't
interesting!

Cheers!
SG

Paavo Helde

unread,
Oct 26, 2010, 12:26:59 PM10/26/10
to
SG <s.ges...@gmail.com> wrote in
news:bcb74c08-83ae-4c1f...@u10g2000yqk.googlegroups.com:
>
> It seems like an interesting concept. Your GC is even trying to invoke
> destructors, though, I would feel uneasy about this in a multi-
> threaded application.

There was a looong thread about this several years ago (here or in clc++m,
don't remember). I got an impression that the firm consensus was that gc
should not call destructors - logically the lost objects would live
forever, only the memory is reclaimed and recycled. This seems to be the
only way to make the program behavior deterministic.

Cheers
Paavo

Leigh Johnston

unread,
Oct 26, 2010, 1:10:03 PM10/26/10
to

Resulting in resource leaks? Seems pointless to me.

/Leigh

Bo Persson

unread,
Oct 26, 2010, 1:15:54 PM10/26/10
to

The idea is that gc solves memory leaks, but nothing else.


Bo Persson


Leigh Johnston

unread,
Oct 26, 2010, 1:38:36 PM10/26/10
to

So you introduce a new feature (gc) at the expense of another feature
(dtors)? Seems pointless to me.

/Leigh

Bo Persson

unread,
Oct 26, 2010, 1:55:24 PM10/26/10
to

Not really. If you want deterministic destruction, you use a
destructor. If you don't care about the objects, and just want to
recycle the memory, you might use a gc.

The "firm consensus" was that you don't want destructors to run
(closing a file, releasing a lock, flushing a buffer, closing a
socket?) at random moments when you try to allocate more memory. Not
that everyone agree on this.


Bo Persson


Öö Tiib

unread,
Oct 26, 2010, 1:58:49 PM10/26/10
to
On 26 okt, 20:10, Leigh Johnston <le...@i42.co.uk> wrote:
> On 26/10/2010 17:26, Paavo Helde wrote:
>
> > SG<s.gesem...@gmail.com>  wrote in

Real problem is that the code did leak the object.

GC calling destructors at undetermined moment of time (no GC can
warrant sooner than "never") will add another problem to that real
problem.

For example your end users have issue. Something tries to reuse the
resource but fails since GC is too lazy for them with that particular
object sometimes. Symptoms that show may be something totally
unrelated to that resource.

For your user-support GC might be always eager. So your user-support
can not reproduce the issue and so there are two annoyed and unhappy
people talking with each other over phone thanks to your "non-
pointless" GC.

Leigh Johnston

unread,
Oct 26, 2010, 2:09:49 PM10/26/10
to

I would argue that it depends on the resource in question as to whether
or not it is ok to free it at a random moment. Memory can be considered
as one such resource.

Not calling destructors means you can not make use of RAII (one of the
most important C++ features). Garbage collected C++ to me seems like a
pointless mental exercise. If calling delete on an object just called
the destructor but left memory deallocation to the garbage collecter
then the garbage collector becomes, at worst, redundant and, at best, a
way to avoid sloppy programmer memory leaks which if RAII was being
employed would be unlikely in any event.

/Leigh

Leigh Johnston

unread,
Oct 26, 2010, 2:12:32 PM10/26/10
to

I replied else-thread that certain resources (of which memory can be
considered one) may be suitable for non-deterministic releasing. C++
and RAII is superiour to C++ and garbage collection; this is my opinion
of course and (hopefully) the opinion of others here too.

/Leigh

Marc

unread,
Oct 26, 2010, 3:24:41 PM10/26/10
to
Leigh Johnston wrote:

> On 26/10/2010 18:55, Bo Persson wrote:
>> Not really. If you want deterministic destruction, you use a
>> destructor. If you don't care about the objects, and just want to
>> recycle the memory, you might use a gc.
>>
>> The "firm consensus" was that you don't want destructors to run
>> (closing a file, releasing a lock, flushing a buffer, closing a
>> socket?) at random moments when you try to allocate more memory. Not
>> that everyone agree on this.
>
> I would argue that it depends on the resource in question as to whether
> or not it is ok to free it at a random moment. Memory can be considered
> as one such resource.
>
> Not calling destructors means you can not make use of RAII (one of the
> most important C++ features). Garbage collected C++ to me seems like a
> pointless mental exercise. If calling delete on an object just called
> the destructor but left memory deallocation to the garbage collecter
> then the garbage collector becomes, at worst, redundant and, at best, a
> way to avoid sloppy programmer memory leaks which if RAII was being
> employed would be unlikely in any event.

You seem to see this as an all-or-nothing. I am not at all a specialist
of garbage collection, but it seems to me that you could still run
destructors normally and predictably for objects that reach the end of
their scope or are explicitly deleted. What remains are those objects
that would be leaked without a GC, and for those you would have the
choice of running the destructor or not. If you program carefully
enough, you know what type of objects may be leaked and ensure their
destructor is an appropriate finalization; otherwise it seems safer to
pretend the objects live forever (true leakage) and reclaim the memory
in a way that can't be observed (ie without running a destructor in
particular). Now with too much separation between the GCed objects and
the regular objects, you may lose some of the advantages of having a GC.

As for the usual misconception that the GC is used only by sloppy
programmers who can't handle memory allocation properly... Let's avoid
this conversation and just discuss the best possible GC under the
assumption that for some project we want one.

Leigh Johnston

unread,
Oct 26, 2010, 3:45:02 PM10/26/10
to

It is not a misconception in the context of *C++* garbage collectors.
If you still allow destructors for "regular objects" as you call them
then all that remains for the GC to clean up are the objects that could
be otherwise leaked by a sloppy programmer's memory allocations, a
sloppy programmer oblivious to RAII. C++ *has* destructors; live what
that fact. C++ has smart pointers and containers; live what that fact.
Use "naked" pointers rarely not routinely. Use RAII routinely not rarely.

/Leigh

Gert-Jan de Vos

unread,
Oct 26, 2010, 4:18:03 PM10/26/10
to

C++ always had deterministic destruction. Existing C++ code and C++
idioms rely on this. If you call destructors when finalizing an object
from a GC, it will break C++ code that was not written with GC in
mind.

I have used MS's C++/CLI a bit which tries to provide full C++ in a
garbage collected environment. It separates the standard destructor
and
the finalizer of an object. The run time makes sure that only one of
these
gets called. The destructor get called as normal, when an automatic
object
reaches end of scope or when a new-ed object is deleted. The finalizer
is
called when the GC collects the object if it was not destructed
before.
The context in which the finalizer runs is entirely different from
that of
the destructor: you cannot use members or base-objects. The fact that
it
also runs non-deterministicly gave us a hard time trying to reproduce
and
debug problems in finalizer code. My current conclusion is that all
objects
that need deterministic life time management (because they own
resources
with side-effects, other than plain memory), must be implemented as
non-GC
objects. Then add a trivial GC-ed wrapper object to expose the object
to
the GC world. Even objects that need large amounts of memory (we work
with
64 MB datasets in a 32 bit OS), are to large to rely on a GC only.

In the end I have to agree with Leigh: C++ style deterministic life
time
management does not mix well with a garbage collector. Still, a unique
advantage of a GC is that a dangling pointer will never refer to
memory
other than the object for which it was allocated.

Öö Tiib

unread,
Oct 26, 2010, 4:31:27 PM10/26/10
to
On 26 okt, 21:12, Leigh Johnston <le...@i42.co.uk> wrote:

Yes, but it seems that you think that RAII and destructors are
unavailable with GC. That is not true. Everything is like normal. Only
thing that GC checks (despite you still explicitly delete everything
when you want to) is that you do not have dangling pointers to it.
Otherwise it does not let you to reuse the underlying memory for
something else with new. That makes dereferencing dangling pointers
not UB but detectable defect with well-predictable outcome. Accessing
something out of bounds still remains UB defect, but since it usually
affects close neighbors it is easier to track down.

Matthias Meixner

unread,
Oct 26, 2010, 5:19:23 PM10/26/10
to
Am 26.10.2010 10:35, schrieb SG:
> On 25 Okt., 23:20, Matthias Meixner wrote:
>>
>> Just in case you are interested, there is a new garbage collector for C++:
>> http://sourceforge.net/projects/meixnergc/
>>
>> [...]
>
> The bullet points you list don't really explain much. Your README is
> much more informative. Maybe, you should consider putting this README
> (or some equivalent documetation) somewhere easy to find so people
> don't have to download the source code first.
>
> It seems like an interesting concept. Your GC is even trying to invoke
> destructors, though, I would feel uneasy about this in a multi-
> threaded application. When and where does garbage collection actually
> take place? It sounds like you're performing "little garbage
> collection steps" during each invocation of your overloaded new
> operator instead of, say, using a separate GC thread.

Yes. Therefore, there is no need to tune the speed of some GC thread.
The garbage collector speed automatically adapts to the speed of the
object allocation.

> Anyhow, it must
> be hard to get it right in a multi-threaded application. I wouldn't be

Garbage is not used by any thread any more or it would not be garbage.
Therefore, I do not expect any additional problems due to multithreading
that would not already exist without the garbage collector.

> surprized if there are a couple of problems/bugs left. BTW: I just
> skimmed over the source code and wondered why you felt the need to
> explicitly disable inlining for a couple functions. Usually, when

These functions had a problem with optimizations enabled with
-fstrict-aliasing when inlined due to some pointer casts. This is
resolved in the newest version in the svn repository.

> people observe that their programs break after turning on compiler
> optimizations, it's due to undefined behaviour... ;-)

In this case the optimizer just overlooked some aliases which resulted
in some wrong assumptions about the code in the optimization phase of
the compiler.

Matthias Meixner

unread,
Oct 26, 2010, 5:28:30 PM10/26/10
to
Am 26.10.2010 19:55, schrieb Bo Persson:
> The "firm consensus" was that you don't want destructors to run
> (closing a file, releasing a lock, flushing a buffer, closing a
> socket?) at random moments when you try to allocate more memory. Not
> that everyone agree on this.

With my code you can manually start the garbage collector to clean up
all garbage. This allows you to clean up garbage at a deterministic
point in time. BTW. this is what the unittest does to test the correct
operation of the garbage collector.
So while it may be more sloppy than having every bit under control it
releases you to keep track of everything yourself. From this point of
view I think it is good to call the destructor to also release
non-memory ressources.

Matthias Meixner

unread,
Oct 26, 2010, 5:59:08 PM10/26/10
to

Just another point to remember: In a mixed environment where you have
both types of objects - garbage collected objects and manually managed
objects, it is vital to call the destructor or you would introduce
memory leaks. For example if an object internally holds some pointer to
some unmanaged memory. Now if the destructor of this object would not be
called the memory used by the object itself would be reclaimed but the
unmanaged memory it internally holds some pointers to would not be
released, i.e. producing a memory leak.

Garrett Hartshaw

unread,
Oct 26, 2010, 10:04:17 PM10/26/10
to
On 10/26/2010 04:31 PM, �� Tiib wrote:
> On 26 okt, 21:12, Leigh Johnston<le...@i42.co.uk> wrote:

IMHO, then the GC seems pointless, as RAII should take care of the
memory problems. While a GC does seem to be a good idea on the surface,
if it comes to be relied on too heavily, a lazy programmer will probably
allow other resources to be leaked than memory, and the GC will do
nothing to stop this. Albeit, lack of GC will do nothing to stop this
either, but by making the programmer concentrate more on what is
destroyed when, the lack of GC makes it more likely that such bugs will
be caught early.
--Garrett Hartshaw

James Kanze

unread,
Oct 27, 2010, 6:12:12 AM10/27/10
to
On Oct 26, 6:38 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 26/10/2010 18:15, Bo Persson wrote:
> > Leigh Johnston wrote:
> >> On 26/10/2010 17:26, Paavo Helde wrote:
> >>> SG<s.gesem...@gmail.com> wrote in
> >>>news:bcb74c08-83ae-4c1f...@u10g2000yqk.googlegroups.com:

> >>>> It seems like an interesting concept. Your GC is even
> >>>> trying to invoke destructors, though, I would feel uneasy
> >>>> about this in a multi- threaded application.

> >>> There was a looong thread about this several years ago (here or in
> >>> clc++m, don't remember). I got an impression that the firm
> >>> consensus was that gc should not call destructors - logically the
> >>> lost objects would live forever, only the memory is reclaimed and
> >>> recycled. This seems to be the only way to make the program
> >>> behavior deterministic.

> >> Resulting in resource leaks? Seems pointless to me.

> > The idea is that gc solves memory leaks, but nothing else.

> So you introduce a new feature (gc) at the expense of another


> feature (dtors)? Seems pointless to me.

You don't remove destructors; they still work as usual. But the
garbage collector doesn't call them. A garbage collector would
call finalize functions, which are something different. If
a class needs a deterministic destructor (very few do), then
it's finalize function might assert that the destructor has been
called.

The most important aspect of garbage collection isn't that it
prevents memory leaks; it's that it prevents, or at least allows
reliably testing dangling pointers. The memory handling is
convenient in certain contexts as well: it's one less thing the
programmer has to worry about, and it certainly works a lot
better than the usual shared_ptr solutions, but it's not
a silver bullet either (and we've all had to deal with Java
programs which leaked).

--
James Kanze

James Kanze

unread,
Oct 27, 2010, 6:15:12 AM10/27/10
to
On Oct 26, 7:09 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 26/10/2010 18:55, Bo Persson wrote:

[...]


> Not calling destructors means you can not make use of RAII
> (one of the most important C++ features).

If you never called destructors, that would be a disaster. But
no one has suggested such a thing.

> Garbage collected C++ to me seems like a pointless mental
> exercise.

It's a useful tool, and it's essential for robustness, in
critical applications (or for that matter, anything connected to
the network, since dangling pointers have been used to break
into systems).

--
James Kanze

Leigh Johnston

unread,
Oct 27, 2010, 6:32:59 AM10/27/10
to

Just as RAII prevents memory and resource leaks, RAII also prevents
dangling pointers being an issue. An experienced (good) C++ programmer
will be using RAII in the form of containers, smart pointers and similar
and will be keeping the use of "naked" pointers to a minimum. I cannot
remember the last time I had a dangling pointer issue, it is a rare bug
(for me at least).

There is nothing fundamentally wrong with shared_ptr. This is a typical
troll statement I would expect from Mr Kanze.

/Leigh

James Kanze

unread,
Oct 27, 2010, 7:17:26 AM10/27/10
to

How?

We're talking about objects with arbitrary lifetimes here.

> An experienced (good) C++ programmer will be using RAII in the
> form of containers, smart pointers and similar and will be
> keeping the use of "naked" pointers to a minimum.

Why? Smart pointers, at least the ones I've seen, don't buy you
anything most of the time.

> I cannot remember the last time I had a dangling pointer
> issue, it is a rare bug (for me at least).

> There is nothing fundamentally wrong with shared_ptr.

Nobody said there was. I use it on a daily basis. It's
a useful tool in certain circumstances. It's not a silver
bullet, however. In some cases, either true garbage collection
or shared_ptr can be used; in such cases, shared_ptr will result
in slightly more work for the programmer, and some cost in
performance, when compared with true garbage collection. In
other cases, shared_ptr doesn't work, and garbage collection
does. And there are cases where shared_ptr works, and garbage
collection doesn't.

> This is a typical troll statement I would expect from Mr
> Kanze.

It's typical of you to revert to ad hominim, rather than to
discuss real technical issues.

--
James Kanze

James Kanze

unread,
Oct 27, 2010, 7:19:53 AM10/27/10
to
On Oct 26, 7:12 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 26/10/2010 18:58, Öö Tiib wrote:

[...]


> I replied else-thread that certain resources (of which memory can be
> considered one) may be suitable for non-deterministic releasing. C++
> and RAII is superiour to C++ and garbage collection; this is my opinion
> of course and (hopefully) the opinion of others here too.

And C++ with RAII *and* garbage collection is superior to
either. Why limit your options? (If all you have is a hammer,
everything looks like a nail. It's best to have many different
tools in your toolbox, so you can use the most appropriate.)

--
James Kanze

Leigh Johnston

unread,
Oct 27, 2010, 7:29:04 AM10/27/10
to

Objects with arbitrary lifetimes can be controlled with a smart pointer,
no need for garbage collection. shared_ptr employs RAII when taking
ownership of an object via its constructor. An object can encapsulate
other sub-objects also utilizing RAII.

/Leigh

Leigh Johnston

unread,
Oct 27, 2010, 7:34:13 AM10/27/10
to
On 27/10/2010 12:19, James Kanze wrote:
> On Oct 26, 7:12 pm, Leigh Johnston<le...@i42.co.uk> wrote:
>> On 26/10/2010 18:58, �� Tiib wrote:
>
> [...]
>> I replied else-thread that certain resources (of which memory can be
>> considered one) may be suitable for non-deterministic releasing. C++
>> and RAII is superiour to C++ and garbage collection; this is my opinion
>> of course and (hopefully) the opinion of others here too.
>
> And C++ with RAII *and* garbage collection is superior to
> either. Why limit your options? (If all you have is a hammer,
> everything looks like a nail. It's best to have many different
> tools in your toolbox, so you can use the most appropriate.)
>

Bad analogy. C++ comes with RAII as standard. C++ comes with
destructors as standard. C++ does not come with a garbage collector as
standard ergo it is not part of the standard C++ "toolbox". Trying to
add garbage collection to C++ is a waste of time as it is not necessary
*IMHO*. Standard C++ and RAII wins. Non-standard garbage collected
monstrosities such as C++/CLI lose.

/Leigh

Juha Nieminen

unread,
Oct 27, 2010, 12:47:57 PM10/27/10
to
Leigh Johnston <le...@i42.co.uk> wrote:
> Not calling destructors means you can not make use of RAII (one of the
> most important C++ features).

I don't understand why using a GC engine in a C++ program would disable
RAII. RAII is related to scope-bound lifetime of local objects. It's not
related to the lifetime of dynamically allocated objects (which must be
managed manually or, in this case, via a GC engine).

Bart van Ingen Schenau

unread,
Oct 28, 2010, 5:39:29 AM10/28/10
to
On Oct 27, 1:17 pm, James Kanze <james.ka...@gmail.com> wrote:
>
> [snip] In

> other cases, shared_ptr doesn't work, and garbage collection
> does.  And there are cases where shared_ptr works, and garbage
> collection doesn't.

Can you give examples of situations where one works but the other not?

>
> --
> James Kanze

Bart v Ingen Schenau

Juha Nieminen

unread,
Oct 28, 2010, 8:36:35 AM10/28/10
to
Bart van Ingen Schenau <ba...@ingen.ddns.info> wrote:
> On Oct 27, 1:17ï¿œpm, James Kanze <james.ka...@gmail.com> wrote:
>>
>> [snip]ï¿œIn

>> other cases, shared_ptr doesn't work, and garbage collection
>> does. ï¿œAnd there are cases where shared_ptr works, and garbage

>> collection doesn't.
>
> Can you give examples of situations where one works but the other not?

The obvious case where shared_ptr won't work properly is with recursive
references (object X contains a shared_ptr to object Y, which contains a
shared_ptr to object X; and in fact, an even simpler case is an object
containing a shared_ptr pointing to itself, although that's slightly less
likely, but not impossible, to happen by accident). This introduces a
leak (the objects are never deleted), and GC engines do not suffer from
this.

Reference-counting smart pointers can also cause objects to be deleted
too soon, while they are still being used, which is a much less known
fact (most programmers have never encountered or heard of such a thing).
It also requires a kind of recursion, but in this case it's not a
recursion of pointers, but a recursion of code. Basically: Module X
has a shared_ptr to object Y, X calls a method of Y, this method calls
back to X, which causes it to drop the shared_ptr, deleting Y. The
execution goes back to the method in Y, which now operates on a deleted
object. Yes this can happen in actual practical examples, and it's also
something that is not a problem with GC.

I don't know, however, what the cases are where smart pointers work
but GC doesn't...

Yannick Tremblay

unread,
Oct 28, 2010, 11:13:53 AM10/28/10
to
In article <ea511b08-c391-4c33...@t13g2000yqm.googlegroups.com>,

James Kanze <james...@gmail.com> wrote:
>On Oct 26, 7:12 pm, Leigh Johnston <le...@i42.co.uk> wrote:
>> On 26/10/2010 18:58, �� Tiib wrote:
>
> [...]
>> I replied else-thread that certain resources (of which memory can be
>> considered one) may be suitable for non-deterministic releasing. C++
>> and RAII is superiour to C++ and garbage collection; this is my opinion
>> of course and (hopefully) the opinion of others here too.
>
>And C++ with RAII *and* garbage collection is superior to
>either. Why limit your options? (If all you have is a hammer,
>everything looks like a nail. It's best to have many different
>tools in your toolbox, so you can use the most appropriate.)

The problem is that garbage collection essentially breaks RAII.

With RAII, all resources are treated the same regardless of if they
are memory or file handle or sockets or whatever. Designing with
RAII, your destructor will take care of closing files or freeing
memory, everything works fine. RAII is absolutely reliable. As long
as all resources are owned by objects and all objects are destroyed,
no resources will ever be leaked.

Once you introduce GC, you are in trouble because you can't rely on
the destructor being run for all objects anymore. It depends,
sometimes the destructor will be run, sometimes the finalise will be
run, depends, who knows.

The result, IMO, is that the great "benefit" of GC which is to reduce
programming complexity by not having to worry about memory management
is totally trumped by the newly introduced complexity which is having
to implement finalise methods and having to worry about leaking
non-memory-only resources due to the destructor not being called.

Yannick

Paavo Helde

unread,
Oct 28, 2010, 12:36:47 PM10/28/10
to
Juha Nieminen <nos...@thanks.invalid> wrote in news:4cc96e53$0$12196
$7b1e...@news.nbl.fi:

> Bart van Ingen Schenau <ba...@ingen.ddns.info> wrote:

>> On Oct 27, 1:17�pm, James Kanze <james.ka...@gmail.com> wrote:
>>>
>>> [snip]�In


>>> other cases, shared_ptr doesn't work, and garbage collection

>>> does. �And there are cases where shared_ptr works, and garbage


>>> collection doesn't.
>>
>> Can you give examples of situations where one works but the other not?

[one-way examples snipped]

>
> I don't know, however, what the cases are where smart pointers work
> but GC doesn't...

Smart pointers are more deterministic than GC, so they work better if one
needs deterministic cleanup of some resource. This holds even for memory,
if the memory chunks are large and the available memory or address space
is limited. (AFAIK at least some GC implementations can accidentally keep
a memory block in use even if there are no pointers to it.)

Also, in some cases it is handy to know the actual reference count of the
object (e.g. when deciding if a separate copy of the object is needed or
not). This can be done easily with a reference-counting smartpointer, but
(I guess) not with GC.

Also, in some convoluted programming style (e.g. Numeric Recipes) the
actually used pointers do not point to the allocated blocks, but before
or after, which may confuse GC.

Cheers
Paavo

Bo Persson

unread,
Oct 28, 2010, 1:16:05 PM10/28/10
to
Yannick Tremblay wrote:
> In article
> <ea511b08-c391-4c33...@t13g2000yqm.googlegroups.com>,
> James Kanze <james...@gmail.com> wrote:
>> On Oct 26, 7:12 pm, Leigh Johnston <le...@i42.co.uk> wrote:
>>> On 26/10/2010 18:58, �� Tiib wrote:
>>
>> [...]
>>> I replied else-thread that certain resources (of which memory can
>>> be considered one) may be suitable for non-deterministic
>>> releasing. C++ and RAII is superiour to C++ and garbage
>>> collection; this is my opinion of course and (hopefully) the
>>> opinion of others here too.
>>
>> And C++ with RAII *and* garbage collection is superior to
>> either. Why limit your options? (If all you have is a hammer,
>> everything looks like a nail. It's best to have many different
>> tools in your toolbox, so you can use the most appropriate.)
>
> The problem is that garbage collection essentially breaks RAII.
>
> With RAII, all resources are treated the same regardless of if they
> are memory or file handle or sockets or whatever. Designing with
> RAII, your destructor will take care of closing files or freeing
> memory, everything works fine. RAII is absolutely reliable. As
> long
> as all resources are owned by objects and all objects are destroyed,
> no resources will ever be leaked.
>

Right. And if the only resources you ever use is memory, GC will take
care of that.

Bo Persson


Dombo

unread,
Oct 28, 2010, 1:51:15 PM10/28/10
to
Op 28-Oct-10 17:13, Yannick Tremblay schreef:
> In article<ea511b08-c391-4c33...@t13g2000yqm.googlegroups.com>,

> The result, IMO, is that the great "benefit" of GC which is to reduce
> programming complexity by not having to worry about memory management
> is totally trumped by the newly introduced complexity which is having
> to implement finalise methods and having to worry about leaking
> non-memory-only resources due to the destructor not being called.

Actually implementing the finalize() method in languages like Java and
C# is usually not recommended since you cannot rely on when, if ever, it
will be called. If you need something to be done no matter how a
function is left one would typically use a finally clause in these
languages. Unfortunately the finally clause puts the burden on the user
rather than on the provider of the functionality. The C# language does
support some features which partially address the lack of RAII support.

Having programmed C++, Java and C# (and a load of other programming
languages), and having most of my work done in C++ I must say that GC
does have its merits (not just for sloppy programmers) though I do miss
RAII at times in languages that do not support it. However different
programming language call for different approaches.

Message has been deleted

Matthias Meixner

unread,
Oct 28, 2010, 4:54:09 PM10/28/10
to
Am 28.10.2010 18:36, schrieb Paavo Helde:
> Also, in some convoluted programming style (e.g. Numeric Recipes) the
> actually used pointers do not point to the allocated blocks, but before
> or after, which may confuse GC.

That's why my garbage collector keeps a pointer to the allocated object
which is independent from the pointer value.

Bart van Ingen Schenau

unread,
Oct 29, 2010, 3:59:36 AM10/29/10
to

Even that would be foiled by the coding style used by Numerical
Recipes.
In that book, they allocate, for example, an array of 100 elements
with the indices [10, 109]. To do this, they ask malloc() for an array
of 100 elements and then adjust the returned pointer to point 10
elements *before* the start of the block returned by malloc.
So, if malloc returned address 20 as the start of that block, the GC
engine will later see a pointer referring to address 10 (which may or
may not have been allocated) and no pointers in the application
referring to the memory area [20..119].

Bart v Ingen Schenau

Yannick Tremblay

unread,
Oct 29, 2010, 6:50:30 AM10/29/10
to
In article <8itpe7...@mid.individual.net>, Bo Persson <b...@gmb.dk> wrote:
>Yannick Tremblay wrote:
>> In article
>> <ea511b08-c391-4c33...@t13g2000yqm.googlegroups.com>,
>> James Kanze <james...@gmail.com> wrote:
>>> On Oct 26, 7:12 pm, Leigh Johnston <le...@i42.co.uk> wrote:
>>>> On 26/10/2010 18:58, 嘱 Tiib wrote:
>>>
>>> [...]
>>>> I replied else-thread that certain resources (of which memory can
>>>> be considered one) may be suitable for non-deterministic
>>>> releasing. C++ and RAII is superiour to C++ and garbage
>>>> collection; this is my opinion of course and (hopefully) the
>>>> opinion of others here too.
>>>
>>> And C++ with RAII *and* garbage collection is superior to
>>> either. Why limit your options? (If all you have is a hammer,
>>> everything looks like a nail. It's best to have many different
>>> tools in your toolbox, so you can use the most appropriate.)
>>
>> The problem is that garbage collection essentially breaks RAII.
>>
>> With RAII, all resources are treated the same regardless of if they
>> are memory or file handle or sockets or whatever. Designing with
>> RAII, your destructor will take care of closing files or freeing
>> memory, everything works fine. RAII is absolutely reliable. As
>> long
>> as all resources are owned by objects and all objects are destroyed,
>> no resources will ever be leaked.
>>
>
>Right. And if the only resources you ever use is memory, GC will take
>care of that.

And so does RAII :-)

Unfortunately, I don't work on things where the only resource needed
is memory.


Yannick Tremblay

unread,
Oct 29, 2010, 7:17:58 AM10/29/10
to
In article <4cc9b81b$0$30708$5fc...@news.tiscali.nl>,

Dombo <do...@disposable.invalid> wrote:
>Op 28-Oct-10 17:13, Yannick Tremblay schreef:
>> In article<ea511b08-c391-4c33...@t13g2000yqm.googlegroups.com>,
>> The result, IMO, is that the great "benefit" of GC which is to reduce
>> programming complexity by not having to worry about memory management
>> is totally trumped by the newly introduced complexity which is having
>> to implement finalise methods and having to worry about leaking
>> non-memory-only resources due to the destructor not being called.
>
>Actually implementing the finalize() method in languages like Java and
>C# is usually not recommended since you cannot rely on when, if ever, it
>will be called. If you need something to be done no matter how a
>function is left one would typically use a finally clause in these
>languages. Unfortunately the finally clause puts the burden on the user
>rather than on the provider of the functionality.

I think this is a fundamental distinction and a fundamental weakness
of "finally" compared to RAII.

>The C# language does
>support some features which partially address the lack of RAII support.
>
>Having programmed C++, Java and C# (and a load of other programming
>languages), and having most of my work done in C++ I must say that GC
>does have its merits (not just for sloppy programmers) though I do miss
>RAII at times in languages that do not support it. However different
>programming language call for different approaches.

Agree.

I don't have a fundamental problem with GC. However, I find it
difficult to use an approach that combine both RAII and GC. The
non-deterministic nature of GC mostly breaks RAII. I'd welcome
enlightment but at the moment, the only way I would find C++ with GC
of benefit would be if I was not using RAII at all and if the only
resources used was memory.

Yannick


Leigh Johnston

unread,
Oct 29, 2010, 12:27:50 PM10/29/10
to

Not true, RAII also applies to objects allocated on the freestore; think
about what happens if the constructor of a partially constructed object
allocated with new throws.

/Leigh

Joshua Maurice

unread,
Oct 29, 2010, 4:07:57 PM10/29/10
to
On Oct 29, 12:59 am, Bart van Ingen Schenau <b...@ingen.ddns.info>
wrote:

> > That's why my garbage collector keeps a pointer to the allocated object
> > which is independent from the pointer value.
>
> Even that would be foiled by the coding style used by Numerical
> Recipes.
> In that book, they allocate, for example, an array of 100 elements
> with the indices [10, 109]. To do this, they ask malloc() for an array
> of 100 elements and then adjust the returned pointer to point 10
> elements *before* the start of the block returned by malloc.
> So, if malloc returned address 20 as the start of that block, the GC
> engine will later see a pointer referring to address 10 (which may or
> may not have been allocated) and no pointers in the application
> referring to the memory area [20..119].

Just as a technical point, isn't that nonconforming code anyway? I
recall that there are rather strict rules about pointer math, and it
might be the case that pointer math-ing a pointer to point to anything
besides an element in the array or one-past-the-end is undefined
behavior. I can't recall the specifics though.

Finally, that undefined behavior is probably too widespread to ignore
for a reliable garbage collector, so this is rather pedantic.

Jorgen Grahn

unread,
Nov 1, 2010, 5:52:43 AM11/1/10
to
On Tue, 2010-10-26, Gert-Jan de Vos wrote:

> On Oct 26, 9:24 pm, Marc <marc.gli...@gmail.com> wrote:
>> Leigh Johnston  wrote:
>> > On 26/10/2010 18:55, Bo Persson wrote:
>> >> Not really. If you want deterministic destruction, you use a
>> >> destructor. If you don't care about the objects, and just want to
>> >> recycle the memory, you might use a gc.

>>
>> >> The "firm consensus" was that you don't want destructors to run
>> >> (closing a file, releasing a lock, flushing a buffer, closing a
>> >> socket?) at random moments when you try to allocate more memory. Not
>> >> that everyone agree on this.
>>
>> > I would argue that it depends on the resource in question as to whether
>> > or not it is ok to free it at a random moment.  Memory can be considered
>> > as one such resource.

>>
>> > Not calling destructors means you can not make use of RAII (one of the
>> > most important C++ features).  Garbage collected C++ to me seems like a
>> > pointless mental exercise.  If calling delete on an object just called
>> > the destructor but left memory deallocation to the garbage collecter
>> > then the garbage collector becomes, at worst, redundant and, at best, a
>> > way to avoid sloppy programmer memory leaks which if RAII was being
>> > employed would be unlikely in any event.
>>
>> You seem to see this as an all-or-nothing. I am not at all a specialist
>> of garbage collection, but it seems to me that you could still run
>> destructors normally and predictably for objects that reach the end of
>> their scope or are explicitly deleted. What remains are those objects
>> that would be leaked without a GC, and for those you would have the
>> choice of running the destructor or not. If you program carefully
>> enough, you know what type of objects may be leaked and ensure their
>> destructor is an appropriate finalization; otherwise it seems safer to
>> pretend the objects live forever (true leakage) and reclaim the memory
>> in a way that can't be observed (ie without running a destructor in
>> particular).  Now with too much separation between the GCed objects and
>> the regular objects, you may lose some of the advantages of having a GC.

I have nothing to add, but G-JdV had messed up the formatting of his
otherwise interesting posting. I've fixed it below:

> C++ always had deterministic destruction. Existing C++ code and C++
> idioms rely on this. If you call destructors when finalizing an object
> from a GC, it will break C++ code that was not written with GC in
> mind.
>
> I have used MS's C++/CLI a bit which tries to provide full C++ in a
> garbage collected environment. It separates the standard destructor
> and the finalizer of an object. The run time makes sure that only one
> of these gets called. The destructor get called as normal, when an
> automatic object reaches end of scope or when a new-ed object is
> deleted. The finalizer is called when the GC collects the object if it
> was not destructed before. The context in which the finalizer runs is
> entirely different from that of the destructor: you cannot use members
> or base-objects. The fact that it also runs non-deterministicly gave
> us a hard time trying to reproduce and debug problems in finalizer
> code.
>
> My current conclusion is that all objects that need deterministic life
> time management (because they own resources with side-effects, other
> than plain memory), must be implemented as non-GC objects. Then add a
> trivial GC-ed wrapper object to expose the object to the GC world.
> Even objects that need large amounts of memory (we work with 64 MB
> datasets in a 32 bit OS), are to large to rely on a GC only.
>
> In the end I have to agree with Leigh: C++ style deterministic life
> time management does not mix well with a garbage collector. Still, a
> unique advantage of a GC is that a dangling pointer will never refer
> to memory other than the object for which it was allocated.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

James Kanze

unread,
Nov 1, 2010, 8:01:41 AM11/1/10
to
On Oct 28, 9:39 am, Bart van Ingen Schenau <b...@ingen.ddns.info>
wrote:

> On Oct 27, 1:17 pm, James Kanze <james.ka...@gmail.com> wrote:
> > [snip] In
> > other cases, shared_ptr doesn't work, and garbage collection
> > does. And there are cases where shared_ptr works, and garbage
> > collection doesn't.

> Can you give examples of situations where one works but the
> other not?

Garbage collection works even when there are cycles; shared_ptr
doesn't. Garbage collection also allows protecting against
dangling pointers.

The most obvious case where shared_ptr works, and garbage
collection doesn't, is when it does something different---you're
using a custom deleters, which don't delete. Otherwise, there
are a few cases where the object represents some critical
resource, and the destructor must be called immediately: most of
the time, some other type of smart pointer (auto_ptr or
scoped_ptr) is more appropriate in such cases, but in some rare
cases, shared_ptr is simpler---typically when for some reason
you need to put the object into a container.

--
James Kanze

James Kanze

unread,
Nov 1, 2010, 8:07:25 AM11/1/10
to
On Oct 27, 11:29 am, Leigh Johnston <le...@i42.co.uk> wrote:
> On 27/10/2010 12:17, James Kanze wrote:

[...]


> >> Just as RAII prevents memory and resource leaks, RAII also
> >> prevents dangling pointers being an issue.

> > How?

> > We're talking about objects with arbitrary lifetimes here.

> Objects with arbitrary lifetimes can be controlled with
> a smart pointer, no need for garbage collection.

That's a blatent contradiction: an object with an arbitrary
lifetime has an arbitrary lifetime, not one controlled by some
smart pointer. In many applications, almost all instances of
delete are "delete this". (And as far as I know, "this" is
never a smart poionter.)

Garbage collection is useful, here, not to manage object
lifetime (garbage collection doesn't manage object lifetime),
but as a safety net, in order to be sure of being able to catch
dangling pointers.

> shared_ptr employs RAII when taking ownership of an object via
> its constructor.

Which is exactly why it cannot be used with objects which have
arbitrary lifetimes.

> An object can encapsulate other sub-objects also utilizing
> RAII.

An object can encapsulate other sub-objects, period. I'm not
sure I'd refer to that as RAII.

--
James Kanze

James Kanze

unread,
Nov 1, 2010, 8:19:00 AM11/1/10
to
On Oct 28, 4:36 pm, Paavo Helde <myfirstn...@osa.pri.ee> wrote:
> Juha Nieminen <nos...@thanks.invalid> wrote in news:4cc96e53$0$12196
> $7b1e8...@news.nbl.fi:

> > Bart van Ingen Schenau <b...@ingen.ddns.info> wrote:
> >> On Oct 27, 1:17 pm, James Kanze <james.ka...@gmail.com> wrote:

[...]


> > I don't know, however, what the cases are where smart pointers work
> > but GC doesn't...

> Smart pointers are more deterministic than GC,

I like that formulation:-). Formally, you can't say "more
deterministic", something is either deterministic or not. (And
in another sense, everything that happens in a computer, at
least in a single thread, is deterministic.) But less formally,
I think you've made a reasonable point. In some specific cases,
it's possible to know more or less when the last pointer will
disappear, and it may be useful to be assured that the object
will be destructed exactly at that moment. (One obvious case is
when you are dealing with a variable number of such objects, all
of which must be destructed on leaving scope. If the objects
aren't copiable---and objects which manage resources normally
aren't---, then you need to use shared_ptr to manage them in
a standard container.)

> so they work better if one needs deterministic cleanup of some
> resource. This holds even for memory, if the memory chunks are
> large and the available memory or address space is limited.
> (AFAIK at least some GC implementations can accidentally keep
> a memory block in use even if there are no pointers to it.)

I don't think that's the case, but it is easy to accidentally
keep a pointer (which will never be used) to a large block, or
a large graph of blocks.

> Also, in some cases it is handy to know the actual reference
> count of the object (e.g. when deciding if a separate copy of
> the object is needed or not). This can be done easily with
> a reference-counting smartpointer, but (I guess) not with GC.

It can be done with garbage collection as well; IIRC, some
implementations of java.lang.StringBuffer used reference
counting (in order to implement copy on write). But if you're
doing reference counting, you control all pointers to the
object, and cyclic references aren't possible (typically because
the object doesn't contain any pointers, e.g. a character
buffer), then garbage collection is rather superfluous.

> Also, in some convoluted programming style (e.g. Numeric
> Recipes) the actually used pointers do not point to the
> allocated blocks, but before or after, which may confuse GC.

Such uses are undefined behavior in C or C++. On the other
hand, they can represent valid optimization techniques for
compilers, at least on certain machines; this is why garbage
collection must be part of the standard. (In practice, such
techniques are not advantageous on most modern architectures, so
compilers don't use them, and the Boehm collector works.)

--
James Kanze

James Kanze

unread,
Nov 1, 2010, 8:23:40 AM11/1/10
to
On Oct 28, 3:13 pm, ytrem...@nyx.net (Yannick Tremblay) wrote:
> In article
> <ea511b08-c391-4c33-85ac-9c8fb2df6...@t13g2000yqm.googlegroups.com>,
> James Kanze <james.ka...@gmail.com> wrote:

> >On Oct 26, 7:12 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> >> On 26/10/2010 18:58, Tiib wrote:

> > [...]
> >> I replied else-thread that certain resources (of which memory can be
> >> considered one) may be suitable for non-deterministic releasing. C++
> >> and RAII is superiour to C++ and garbage collection; this is my opinion
> >> of course and (hopefully) the opinion of others here too.

> >And C++ with RAII *and* garbage collection is superior to
> >either. Why limit your options? (If all you have is a hammer,
> >everything looks like a nail. It's best to have many different
> >tools in your toolbox, so you can use the most appropriate.)

> The problem is that garbage collection essentially breaks RAII.

That is completely false; the two are completely orthogonal.

> With RAII, all resources are treated the same regardless of if
> they are memory or file handle or sockets or whatever.

Which isn't necessarily an advantage.

> Designing with RAII, your destructor will take care of closing
> files or freeing memory, everything works fine. RAII is
> absolutely reliable. As long as all resources are owned by
> objects and all objects are destroyed, no resources will ever
> be leaked. Once you introduce GC, you are in trouble because
> you can't rely on the destructor being run for all objects
> anymore. It depends, sometimes the destructor will be run,
> sometimes the finalise will be run, depends, who knows.

No. You know when the destructor will run, and when it won't.

> The result, IMO, is that the great "benefit" of GC which is to reduce
> programming complexity by not having to worry about memory management
> is totally trumped by the newly introduced complexity which is having
> to implement finalise methods and having to worry about leaking
> non-memory-only resources due to the destructor not being called.

Actual experience shows otherwise.

--
James Kanze

Leigh Johnston

unread,
Nov 1, 2010, 8:31:58 AM11/1/10
to

It is not a contradiction: I use smart pointers to control arrays in my
scripting language and it is up to the script to determine when arrays
are allocated and deallocated; if this is not "arbitrary" then I don't
know what is.

Dangling pointers and memory leaks are problems which disappear when
RAII is used. RAII is superiour to garbage collection. RAII is
deterministic. Destructors exist, live with that fact.

/Leigh

Leigh Johnston

unread,
Nov 1, 2010, 9:02:14 AM11/1/10
to
On 01/11/2010 12:07, James Kanze wrote:

If by "arbitrary lifetime" you mean the (totally obvious) effect that GC
object deallocation is non-deterministic (from the point of view of the
client programmer) then yes shared_ptr control is not "arbitrary"
however the very fact that object deallocation is non-deterministic and
that destructors cannot free certain resources in an "arbitrary"
(non-deterministic) manner are facts that just highlight how useless
garbage collection in C++ actually is.

I would have thought you were less clueless and be able to acertain that
by "arbitrary lifetime" *I* was refering to the fact that one can have
multiple shared_ptr instances controlling the same object instead of
having one place in code to explicitly delete the controlled object.

/Leigh

James Kanze

unread,
Nov 1, 2010, 11:09:10 AM11/1/10
to
On Oct 29, 11:17 am, ytrem...@nyx.net (Yannick Tremblay) wrote:
> In article <4cc9b81b$0$30708$5fc3...@news.tiscali.nl>,

> Dombo <do...@disposable.invalid> wrote:

[...]


> I don't have a fundamental problem with GC. However, I find it
> difficult to use an approach that combine both RAII and GC. The
> non-deterministic nature of GC mostly breaks RAII. I'd welcome
> enlightment but at the moment, the only way I would find C++ with GC
> of benefit would be if I was not using RAII at all and if the only
> resources used was memory.

I think the key is to forget about "resources" (as something
special) for a moment, and think in terms of object lifetime.
Different objects have different constraints with regards to
lifetime:

-- For value oriented objects, it's largely irrelevant. The
same is true for a certain number of what I call
agents---objects which (typically) have no state of their
own, but exist only to do things on other objects (visiters,
observers, etc., which "connect" different objects).
Generally, these objects are allocated on the stack, and
copied as needed into the appropriate scope; the exceptions
are when agents need to be polymorphic, or when the objects
are too expensive to copy. Garbage collection is the
simplest solution for these, although normally, shared_ptr
also works fairly well.

-- Entity objects, whose lifetime is controlled by the
application semantics. Sometimes, they can just silently
die, in which case, garbage collection is all you need.
Most of the time, however (at least in my applications),
there has been a need for some sort of definite "death"; the
objects can't (or shouldn't) be used after this death, and
there may be specific behaviors associated with this death.

Neither garbage collection nor RAII (shared_ptr or other)
help in managing this lifetime, since it is determined by
events outside the program. And it's almost always
necessary to use some variant of the observer pattern to
notify all interested parties when its death occurs. (In
some simple cases, a combination of weak_ptr and
a shared_ptr to self in the object might be doable, but the
results are at least as complicated as a manual
implementation of the observer pattern, and can easily be
broken by future evolutions.) In such cases, garbage
collection can be used to improve robustness: the underlying
memory cannot be used for anything else as long as any
pointers to it exist (which shouldn't be the case, but
errors do happen), so you can mark it in some way, and test
for validity at the start of each member function.

-- Objects which manage external resources. These are the few
objects for which the term RAII is really appropriate. They
will normally be non-copiable, and in my experience, almost
always local variables. For the rare cases where local
variables are not appropriate, shared_ptr is (and not
garbage collection).

This is, of course, very general, and there are doubtlessly
other special cases which will occur. Still, my point remains:
you need to understand the role and the responsibilities of the
class (or the class hierarchy) before doing anything with the
class, and once you've done that, the choice of leaving it to
garbage collection, using shared_ptr, never allocating it
dynamically, or yet some other strategy, can be made.

--
James Kanze

James Kanze

unread,
Nov 1, 2010, 11:13:33 AM11/1/10
to

> >>> How?

> It is not a contradiction: I use smart pointers to control


> arrays in my scripting language and it is up to the script to
> determine when arrays are allocated and deallocated; if this
> is not "arbitrary" then I don't know what is.

So how do you use smart pointers? shared_ptr obviously doesn't
work, since you cannot delete an object managed by a shared_ptr
at an arbitrary time.

> Dangling pointers and memory leaks are problems which
> disappear when RAII is used.

So you believe in silver bullets.

> RAII is superiour to garbage collection.

RAII is orthogonal to garbage collection. A language with both
(e.g. C++ with the Boehm collector) is better than a language
with just one (C++ without the Boehm collector, or C#).

> RAII is deterministic. Destructors exist, live with that
> fact.

You seem to be the only person who seems to doubt it.

--
James Kanze

James Kanze

unread,
Nov 1, 2010, 11:24:02 AM11/1/10
to
On Nov 1, 1:02 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 01/11/2010 12:07, James Kanze wrote:

> If by "arbitrary lifetime" you mean the (totally obvious)
> effect that GC object deallocation is non-deterministic

What on earth has that to do with anything? Given that garbage
collection has nothing to do with the lifetime of an object.
(It would help if you'd at least read the articles you respond
to.)

Arbirary lifetime means that the lifetime of the object depends
on some external event: a request to a server, a connection, the
state of hardware, a specific user interaction, etc. When that
event occurs, the object's lifetime must end. Regardless of
whether there is a shared_ptr floating around referring to it,
or anything else.

[...]


> I would have thought you were less clueless and be able to acertain that
> by "arbitrary lifetime" *I* was refering to the fact that one can have
> multiple shared_ptr instances controlling the same object instead of
> having one place in code to explicitly delete the controlled object.

Exactly. You no longer have arbitrary lifetime, you have
non-determistic lifetime. The object lifetime ends when the
last shared_ptr is destructed. Whenever that is... in all but
a few special cases, you really don't know (and the most common
reason for using shared_ptr is that you don't want to know).

The problem with shared_ptr (and delete in general, but you can
avoid it with delete if you have garbage collection installed)
is that memory allocation is strictly linked to object lifetime.
This is what you don't want; you don't want the memory
underlying the object to be recycled until the last pointer to
the object disappears, but you cannot use that as a criteria for
ending object lifetime; you must end the object lifetime even if
there are pointers to the object.

--
James Kanze

Leigh Johnston

unread,
Nov 1, 2010, 11:33:49 AM11/1/10
to

The array in my scripting language is implemented as a std::vector
instance controlled by a shared_ptr. A script will determine when an
array is allocated and deallocated (my definition of arbitrary). The
shared_ptr instances are member variables of "array reference" objects
which are controlled by a container representing the script's "runtime
stack".

>
>> Dangling pointers and memory leaks are problems which
>> disappear when RAII is used.
>
> So you believe in silver bullets.

It is not a silver bullet; it is C++ fact.

>
>> RAII is superiour to garbage collection.
>
> RAII is orthogonal to garbage collection. A language with both
> (e.g. C++ with the Boehm collector) is better than a language
> with just one (C++ without the Boehm collector, or C#).
>
>> RAII is deterministic. Destructors exist, live with that
>> fact.
>
> You seem to be the only person who seems to doubt it.
>

I don't know what you mean by that statement...

/Leigh

Alf P. Steinbach /Usenet

unread,
Nov 1, 2010, 11:47:52 AM11/1/10
to
* James Kanze, on 01.11.2010 16:13:

Uhm, James, it seems like you're splitting hairs, and assuming unreasonable
meanings of statements.

OK, that can be fun, but really. :-)

Cheers,

- Alf

--
blog at <url: http://alfps.wordpress.com>

Leigh Johnston

unread,
Nov 1, 2010, 12:02:57 PM11/1/10
to
On 01/11/2010 15:24, James Kanze wrote:
> On Nov 1, 1:02 pm, Leigh Johnston<le...@i42.co.uk> wrote:
>> On 01/11/2010 12:07, James Kanze wrote:
>
>> If by "arbitrary lifetime" you mean the (totally obvious)
>> effect that GC object deallocation is non-deterministic
>
> What on earth has that to do with anything? Given that garbage
> collection has nothing to do with the lifetime of an object.
> (It would help if you'd at least read the articles you respond
> to.)
>
> Arbirary lifetime means that the lifetime of the object depends
> on some external event: a request to a server, a connection, the
> state of hardware, a specific user interaction, etc. When that
> event occurs, the object's lifetime must end. Regardless of
> whether there is a shared_ptr floating around referring to it,
> or anything else.

You have obviously reverted to troll mode so I am not sure how much
effort I should expend in replying.

Your definition of "arbitrary lifetime" seems to be a nonsense to me;
some external event will cause some code to be run and if that code
explicitly deletes an associated object then it's lifetime can no longer
be considered "arbitrary" (or not in the sense of my understanding of
the word) but instead "well defined". I feel you are deliberately
muddying the semantic waters which is typical behaviour for a troll.

C++ does not require that a destructor must be called for its lifetime
to be considered over:

"The lifetime of an object of type T ends when:
— if T is a class type with a non-trivial destructor (12.4), the
destructor call starts, or
— the storage which the object occupies is reused or released."

Given this and the fact that non-trivial destructors are problematic for
garbage collecters (as some resources cannot be freed arbitrarily) it
can be said that a garbage collector that deallocates the memory
associated with an object is ending that object's lifetime. Such
garbage collectors are virtually useless (a waste of time) as they only
solve the limited problems of memory leaks and dangling pointers which
disappear when RAII is employed. RAII and deterministic destruction is
the C++ solution to the problem you seem to think that garbage
collection solves.

>
> [...]
>> I would have thought you were less clueless and be able to acertain that
>> by "arbitrary lifetime" *I* was refering to the fact that one can have
>> multiple shared_ptr instances controlling the same object instead of
>> having one place in code to explicitly delete the controlled object.
>
> Exactly. You no longer have arbitrary lifetime, you have
> non-determistic lifetime. The object lifetime ends when the
> last shared_ptr is destructed. Whenever that is... in all but
> a few special cases, you really don't know (and the most common
> reason for using shared_ptr is that you don't want to know).

Rubbish, destruction of shared_ptr instances is deterministic as is the
resulting ending of the controlled object's lifetime but this lifetime
ending can also be considered arbitrary depending on the use-case.
Garbage collector deallocations are both non-determinisitc and
arbitrary. If you still disagree then I suggest you look up the word
"arbitrary" in a dictionary.

>
> The problem with shared_ptr (and delete in general, but you can
> avoid it with delete if you have garbage collection installed)
> is that memory allocation is strictly linked to object lifetime.
> This is what you don't want; you don't want the memory
> underlying the object to be recycled until the last pointer to
> the object disappears, but you cannot use that as a criteria for
> ending object lifetime; you must end the object lifetime even if
> there are pointers to the object.
>
> --
> James Kanze

On the contrary you *do* want memory underyling an object to be freed at
the same time the object's lifetime ends. Using a pointer to an object
whose lifetime has ended but whose memory has not been freed sounds like
a bug to me.

/Leigh

Leigh Johnston

unread,
Nov 1, 2010, 12:07:27 PM11/1/10
to
On 01/11/2010 15:09, James Kanze wrote:
> Neither garbage collection nor RAII (shared_ptr or other)
> help in managing this lifetime, since it is determined by
> events outside the program. And it's almost always
> necessary to use some variant of the observer pattern to
> notify all interested parties when its death occurs. (In
> some simple cases, a combination of weak_ptr and
> a shared_ptr to self in the object might be doable, but the
> results are at least as complicated as a manual
> implementation of the observer pattern, and can easily be
> broken by future evolutions.) In such cases, garbage
> collection can be used to improve robustness: the underlying
> memory cannot be used for anything else as long as any
> pointers to it exist (which shouldn't be the case, but
> errors do happen), so you can mark it in some way, and test
> for validity at the start of each member function.

Lulz, are you being serious? "Test the object for validity at the start
of each member function"? Seriously? Either get a clue Mr Kanze or
stop trolling as it is tedious.

/Leigh

Leigh Johnston

unread,
Nov 1, 2010, 12:11:30 PM11/1/10
to
On 01/11/2010 16:02, Leigh Johnston wrote:
> On the contrary you *do* want memory underyling an object to be freed at
> the same time the object's lifetime ends. Using a pointer to an object
> whose lifetime has ended but whose memory has not been freed sounds like
> a bug to me.
>

"freed or reused" I should have said (for the trollish pedants out there).

/Leigh

Keith H Duggar

unread,
Nov 1, 2010, 2:23:48 PM11/1/10
to
On Nov 1, 11:24 am, James Kanze <james.ka...@gmail.com> wrote:
> Arbirary lifetime means that the lifetime of the object depends
> on some external event: a request to a server, a connection, the
> state of hardware, a specific user interaction, etc.  When that
> event occurs, the object's lifetime must end.  Regardless of
> whether there is a shared_ptr floating around referring to it,
> or anything else.

So in the program at the end of this post, the integer pointed
to by n has "arbitrary lifetime" correct? Since the user must press
'y' to destroy it. And it would have exactly the same "arbitrary
lifetime" whether I used a naked pointer or a smart_ptr
instead of auto_ptr right?

So how is it the case that smart_ptr does not support objects
with arbitrary lifetime? Object lifetime is determined by the
/program logic/ as a whole not just the type of smart_pointer.

By the way, smart_ptr along with weak_ptr allows arbitrary lifetime
with multiple pointers that survive beyond the controlling pointer(s)
lifetime with error detection (in the form of thrown exceptions) when
a dangling weak_ptr is dereferenced.

Exactly the same level of protection from dangling pointers (though
not
automated obviously) you would have in a gc system that created
"zombie"
objects (by zeroing out memory or whatever).

<code>
#include <iostream>
#include <memory>

int main ( )
{
std::auto_ptr<int> n(new int(42)) ;
while ( std::cin ) {
char c = 0 ;
std::cout << "destroy? : " ;
std::cin >> c ;
if ( c == 'y' ) {
n.reset() ;
break ;
}
}

return 0 ;
}
</code>

KHD

James Kanze

unread,
Nov 1, 2010, 3:12:33 PM11/1/10
to
On Nov 1, 6:23 pm, Keith H Duggar <dug...@alum.mit.edu> wrote:
> On Nov 1, 11:24 am, James Kanze <james.ka...@gmail.com> wrote:

> > Arbirary lifetime means that the lifetime of the object
> > depends on some external event: a request to a server,
> > a connection, the state of hardware, a specific user
> > interaction, etc. When that event occurs, the object's
> > lifetime must end. Regardless of whether there is
> > a shared_ptr floating around referring to it, or anything
> > else.

> So in the program at the end of this post, the integer pointed
> to by n has "arbitrary lifetime" correct? Since the user must
> press 'y' to destroy it. And it would have exactly the same
> "arbitrary lifetime" whether I used a naked pointer or
> a smart_ptr instead of auto_ptr right?

You can create trivial and uninteresting cases, where the
arbitrary lifetime corresponds to a scope. In realistic cases,
that won't be the case.

> So how is it the case that smart_ptr does not support objects
> with arbitrary lifetime? Object lifetime is determined by the
> /program logic/ as a whole not just the type of smart_pointer.

Object lifetime is should be determined by the program logic,
not by the presence or absence of some pointer to the object.
(For objects where lifetime is an issue.)

> By the way, smart_ptr along with weak_ptr allows arbitrary
> lifetime with multiple pointers that survive beyond the
> controlling pointer(s) lifetime with error detection (in the
> form of thrown exceptions) when a dangling weak_ptr is
> dereferenced.

There are some applications where that can be made to work,
where you can hierarchize the navigation in some way. At a cost
of a lot of extra complexity and fragility. And it doesn't
always work.

> Exactly the same level of protection from dangling pointers
> (though not automated obviously) you would have in a gc system
> that created "zombie" objects (by zeroing out memory or
> whatever).

> <code>
> #include <iostream>
> #include <memory>

> int main ( )
> {
> std::auto_ptr<int> n(new int(42)) ;
> while ( std::cin ) {
> char c = 0 ;
> std::cout << "destroy? : " ;
> std::cin >> c ;
> if ( c == 'y' ) {
> n.reset() ;
> break ;
> }
> }
> return 0 ;}
> </code>

Replace auto_ptr with shared_ptr. Then make a copy of it in an
object somewhere. Continue operating after the break, handling
other commands.

Using smart pointers like this is a disaster waiting to happen.

--
James Kanze

Leigh Johnston

unread,
Nov 1, 2010, 3:39:24 PM11/1/10
to

Guff. Using smart pointers like what exactly? There is nothing
fundamentally wrong with shared_ptr. If it is correct *program logic*
to "make a copy of it in an object somewhere" then it is not a disaster
waiting to happen; the set of controlling instances controlling its
lifetime has simply been reduced by one.

/Leigh

Matthias Meixner

unread,
Nov 1, 2010, 5:57:25 PM11/1/10
to
Am 01.11.2010 17:07, schrieb Leigh Johnston:
> Lulz, are you being serious? "Test the object for validity at the start
> of each member function"? Seriously? Either get a clue Mr Kanze or
> stop trolling as it is tedious.

What should be wrong with it? On the contrary this is common practice
when writing security critical code: Check the validity of all
parameters and the this pointer is just one of them. Not obeying this
rule is one source of many security problems (e.g. resulting in buffer
overflows).

- Matthias Meixner

Leigh Johnston

unread,
Nov 1, 2010, 6:07:09 PM11/1/10
to

Bullshit. The rule that needs to be obeyed is that you don't use
pointers to objects whose lifetime has ended. Once an object's lifetime
has ended the memory it occupied should either be freed or reused, not
marked as "invalid" by the programmer as doing so is plain crazy (this
pointer is not valid). An legitimate exception to this, for example,
would be a debug build of a memory allocator but this is the
implementation's responsibility and not the programmer's.

/Leigh

Matthias Meixner

unread,
Nov 1, 2010, 6:36:00 PM11/1/10
to

"invalid" is not the same as "whose lifetime has ended". Objects may be
in an invalid state that forbids to call most of its members but they
may still be alive.

Leigh Johnston

unread,
Nov 1, 2010, 6:51:23 PM11/1/10
to

Yes and this "invalid state" is just another "valid" state that an
object can be in and forms part of the object's class invariant, i.e. it
has nothing to do with garbage collection.

/Leigh

Öö Tiib

unread,
Nov 2, 2010, 2:43:14 AM11/2/10
to

GC is for to have well-defined "destroyed and deallocated" state for
objects of dynamic storage. What is so bad about it? Real people have
often to maintain ugly C++ code-bases. It is pointless to mention that
good programmer does not write ugly things. Where to take them
"goods"? Check reality. Majority of C++ code on our planet is written
by sub-average programmers.

Static analyze tools can find lot of null pointer dereferences,
uninitialized variable usage, return value ignoring and bounds
violations. Run one on a unknown codebase and it discovers hundreds of
such. Can you point at static analyze tool that finds out noteworthy
fraction of dangling pointer usages in reasonable-sized code base?
There are none such things. That leaves run-time checks.

Touching dangling pointer runtime is UB both in standard and in
reality. Closest tool to check dangling pointers run-time is valgrind.
Debugging with it is close-to impossibly slow. Best performing
alternative to GC is weak_ptr. weak_ptr is so ugly when used that
every time i see one i want to kill it. I would put weak_ptr among
debugging tools not GC. GC provides weak_ptr-like-state for raw
pointers. GC does not affect performance so much like other debugging
tools so it does not deserve to be put among these. Some claim it even
improves performance. I have also observed it results with better
overall performance compared with weak_ptr usage.

The main thing what i do not understand is why you care? Do not use it
if you do not want it. Library like boost. Only changes features of
language slightly.

James Kanze

unread,
Nov 2, 2010, 7:59:17 AM11/2/10
to

And how. I write programs which work. I've worked on a lot of
more or less critical systems.

> Either get a clue Mr Kanze or stop trolling as it is tedious.

I'd say that you're the one who needs to get a clue. Your lack
of experience is showing.

--
James Kanze

Bart van Ingen Schenau

unread,
Nov 2, 2010, 8:10:21 AM11/2/10
to
On Oct 29, 9:07 pm, Joshua Maurice <joshuamaur...@gmail.com> wrote:
>
> Just as a technical point, isn't that nonconforming code anyway? I
> recall that there are rather strict rules about pointer math, and it
> might be the case that pointer math-ing a pointer to point to anything
> besides an element in the array or one-past-the-end is undefined
> behavior. I can't recall the specifics though.

You are completely right in your description of the pointer-math rules
and that my example incurs undefined behaviour.

>
> Finally, that undefined behavior is probably too widespread to ignore
> for a reliable garbage collector, so this is rather pedantic.

Bart v Ingen Schenau

Keith H Duggar

unread,
Nov 2, 2010, 8:40:34 AM11/2/10
to

The problem is that answering that question requires detailed
and clear thinking exploring all ramifications. Such analysis is
far beyond what the majority of posters bring to the table in a
casual unmoderated forum such as this.

Fortunately, there are people willing to invest the required work
to clearly think through and to discuss the issues more completely
in a moderated forum. Here is a place to start:

http://groups.google.com/group/comp.lang.c++.moderated/msg/35b67606d4c81fa2

to understand the problems with zombie states. But you should
read that entire thread which, though deceptively named, is about
GC in C++. If you don't want to read the whole thread, you should
at least pay very careful attention to the points David Abrahams
makes.

KHD

Leigh Johnston

unread,
Nov 2, 2010, 9:17:27 AM11/2/10
to

My lack of experience? Lol. I do have a lack of experience working on
now irrelevent 30/40 year old systems that is true. I am the one
advocating RAII over garbage collection in a C++ newsgroup; perhaps you
would feel more comfortable trolling in a Java newsgroup.

/Leigh

Leigh Johnston

unread,
Nov 2, 2010, 9:50:36 AM11/2/10
to
On 02/11/2010 11:59, James Kanze wrote:
> On Nov 1, 4:07 pm, Leigh Johnston<le...@i42.co.uk> wrote:
>> On 01/11/2010 15:09, James Kanze wrote:
>
>>> Neither garbage collection nor RAII (shared_ptr or other)
>>> help in managing this lifetime, since it is determined by
>>> events outside the program. And it's almost always
>>> necessary to use some variant of the observer pattern to
>>> notify all interested parties when its death occurs. (In
>>> some simple cases, a combination of weak_ptr and
>>> a shared_ptr to self in the object might be doable, but the
>>> results are at least as complicated as a manual
>>> implementation of the observer pattern, and can easily be
>>> broken by future evolutions.) In such cases, garbage
>>> collection can be used to improve robustness: the underlying
>>> memory cannot be used for anything else as long as any
>>> pointers to it exist (which shouldn't be the case, but
>>> errors do happen), so you can mark it in some way, and test
>>> for validity at the start of each member function.
>
>> Lulz, are you being serious? "Test the object for validity at
>> the start of each member function"? Seriously?
>
> And how. I write programs which work. I've worked on a lot of
> more or less critical systems.
>

More troll lulz. I have already come to the conclusion that garbage
collection is anathema to safety critical systems; is my lack of
experience showing when reaching this conclusion?

/Leigh

Paavo Helde

unread,
Nov 2, 2010, 2:31:22 PM11/2/10
to
Leigh Johnston <le...@i42.co.uk> wrote in
news:DdmdnfSagLP4kk3R...@giganews.com:

> I am the one
> advocating RAII over garbage collection in a C++ newsgroup;

You don't have to advocate RAII here, I believe most people here are quite
fond of C++ RAII. Especially you don't have to advocate RAII *over* GC as
there is no inherent reason they should contradict each other or even
interfere with each other.

I have not used GC myself (as I have not been convinced this fits the kind
of projects I am involved with), but I do not attempt to prohibit other
people from using it!

Paavo

Leigh Johnston

unread,
Nov 2, 2010, 2:37:05 PM11/2/10
to
On 02/11/2010 18:31, Paavo Helde wrote:
> Leigh Johnston<le...@i42.co.uk> wrote in
> news:DdmdnfSagLP4kk3R...@giganews.com:
>
>> I am the one
>> advocating RAII over garbage collection in a C++ newsgroup;
>
> You don't have to advocate RAII here, I believe most people here are quite
> fond of C++ RAII. Especially you don't have to advocate RAII *over* GC as
> there is no inherent reason they should contradict each other or even
> interfere with each other.
>

The problem is that RAII requires destructors to be run; when exactly do
you run the destructor for a garbage collected object? Unlike memory
some resources can not be freed arbitrarily when the garbage collector
feels like running. If you have to explicity call a cleanup method to
close resources then why bother with a garbage collector at all?

> I have not used GC myself (as I have not been convinced this fits the kind
> of projects I am involved with), but I do not attempt to prohibit other
> people from using it!
>
> Paavo

My view is that garbage collected C++ sucks, I have yet to be convinced
of the validity of an alternative view. :)

/Leigh

Öö Tiib

unread,
Nov 2, 2010, 3:15:45 PM11/2/10
to
>    http://groups.google.com/group/comp.lang.c++.moderated/msg/35b67606d4...

>
> to understand the problems with zombie states. But you should
> read that entire thread which, though deceptively named, is about
> GC in C++. If you don't want to read the whole thread, you should
> at least pay very careful attention to the points David Abrahams
> makes.

I have read plenty of such discussions.

1) No one argues with the fact that GC adds well-defined and
detectable corpse state for detecting dangling raw pointer
dereference.

2) I do not argue that it is far from what is GC in C# or Java. Call
it something else I don't care.

3) No one argues that without GC dangling raw pointer dereference is
worst to detect programming error. Both with statical analysis and run-
time.

4) I do not claim that there are lot of cases when raw pointers are
needed in modern C++. There is huge pile of templated containers and
the shared_ptr, scoped_ptr, unique_ptr, auto_ptr, intrusive_ptr,
cow_ptr and just describe it, its there. C++ application with zero raw
pointers is therefore very possible.

5) Because of 4) GC as core language feature would be waste. It is
fine as option/library only for cases when raw pointers are used/
taken.

6) Classes for what raw pointers *are never* taken do not need to be
run-time checked for zombieness. Lack of such checks in classes for
what raw pointers *are* taken is statically analyzable. Such checks
may even help without GC on some implementations (despite it is UB
then).

7) I haven't seen anyone saying that he loves weak_ptr. No wonder. It
is ugly.

8) weak_ptr and shared_ptr combo can be on lot of cases refactored
back to raw pointer with GC. That gains performance ... or at least my
profiling attempts show so. Checks should be anyway there with
weak_ptr. shared_ptr is fine on lot of cases but does not also deserve
any silver-bullet-dance-festivals, it has refcount to manage plus
additional indirection so it costs.

9) GC makes necromancy possible, but what i am a necromancer? No,
necromancy is evil and black magic and it is easier to detect than
dangling pointer.

10) People who are making money by consulting and training C++ (like
Dave Abrahams) certainly love that C++ is such a pile of gotchas and
undefined behaviors from top to bottom. People who write software have
not entirely overlapping goals with them.

Dilip

unread,
Nov 2, 2010, 3:18:01 PM11/2/10
to
On Nov 2, 1:37 pm, Leigh Johnston <le...@i42.co.uk> wrote:
>
> My view is that garbage collected C++ sucks, I have yet to be convinced
> of the validity of an alternative view. :)

And you won't be because the moment someone disagrees with you, you
will probably start questioning their manhood, their lineage and what
not. As a passive observer I find your posts needlessly arrogant and
reeks of a general my-way-or-the-highway mentality that adds zero
value to any discussion you participate.

I don't know why long-timers like James Kanze even bother to engage
you.

Leigh Johnston

unread,
Nov 2, 2010, 3:36:21 PM11/2/10
to

And you are a troll. I don't recall ever using an insult related to
manhood or lineage. Calling somebody for "bullshit" or "trolling" is
perfectly fine in a forum such as this.

/Leigh

Andy Venikov

unread,
Nov 2, 2010, 4:55:36 PM11/2/10
to
On 11/1/2010 8:07 AM, James Kanze wrote:
> On Oct 27, 11:29 am, Leigh Johnston<le...@i42.co.uk> wrote:

<snip>

>> Objects with arbitrary lifetimes can be controlled with
>> a smart pointer, no need for garbage collection.
>
> That's a blatent contradiction: an object with an arbitrary
> lifetime has an arbitrary lifetime, not one controlled by some
> smart pointer. In many applications, almost all instances of
> delete are "delete this". (And as far as I know, "this" is
> never a smart poionter.)
>

<snip>

Ok, I have nothing to add here, but I think a small clarification may
help this discussion.

Leigh, do you mean to say that you're talking about objects with
arbitrary BUT *deterministic* lifetime? In that case it makes sense and
I don't see any contradiction here.

Andy.

Andy Venikov

unread,
Nov 2, 2010, 4:57:38 PM11/2/10
to

Ok, I just read you other post. It looks like that's exactly what you mean.


Leigh Johnston

unread,
Nov 2, 2010, 5:14:16 PM11/2/10
to

It is yes. :)

/Leigh

Paavo Helde

unread,
Nov 2, 2010, 6:23:36 PM11/2/10
to
Leigh Johnston <le...@i42.co.uk> wrote in
news:aJ6dndtJsrTNx03R...@giganews.com:

> On 02/11/2010 18:31, Paavo Helde wrote:
>> Leigh Johnston<le...@i42.co.uk> wrote in
>> news:DdmdnfSagLP4kk3R...@giganews.com:
>>
>>> I am the one
>>> advocating RAII over garbage collection in a C++ newsgroup;
>>
>> You don't have to advocate RAII here, I believe most people here are
>> quite fond of C++ RAII. Especially you don't have to advocate RAII
>> *over* GC as there is no inherent reason they should contradict each
>> other or even interfere with each other.
>>
>
> The problem is that RAII requires destructors to be run;

Only when a resource needs to be deallocated. In case of GC the memory
resource will be deallocated without RAII, so RAII would not be needed
for that.

> when exactly
> do you run the destructor for a garbage collected object?

That's easy: never. This is the only deterministic option.

> Unlike
> memory some resources can not be freed arbitrarily when the garbage
> collector feels like running.

So I have to take care about not using GC for objects managing non-memory
resources.

> If you have to explicity call a cleanup
> method to close resources then why bother with a garbage collector at
> all?

That's why I have not used GC in my projects. However, I can imagine
other types of projects where it could work better.

Paavo

Yannick Tremblay

unread,
Nov 3, 2010, 10:10:31 AM11/3/10
to
In article <9462474b-de0d-4685...@l17g2000yqe.googlegroups.com>,
James Kanze <james...@gmail.com> wrote:
>On Oct 28, 3:13 pm, ytrem...@nyx.net (Yannick Tremblay) wrote:
>> In article
>> <ea511b08-c391-4c33-85ac-9c8fb2df6...@t13g2000yqm.googlegroups.com>,
>> James Kanze <james.ka...@gmail.com> wrote:
>
>> >On Oct 26, 7:12 pm, Leigh Johnston <le...@i42.co.uk> wrote:
>> >> On 26/10/2010 18:58, Tiib wrote:
>
>> > [...]
>> >> I replied else-thread that certain resources (of which memory can be
>> >> considered one) may be suitable for non-deterministic releasing. C++
>> >> and RAII is superiour to C++ and garbage collection; this is my opinion
>> >> of course and (hopefully) the opinion of others here too.
>
>> >And C++ with RAII *and* garbage collection is superior to
>> >either. Why limit your options? (If all you have is a hammer,
>> >everything looks like a nail. It's best to have many different
>> >tools in your toolbox, so you can use the most appropriate.)
>
>> The problem is that garbage collection essentially breaks RAII.
>
>That is completely false; the two are completely orthogonal.

I am afraid I don't see them as such. I can agree that it is possible
for them to coexist but *completely* orthogonal would require them to
have no effect on one another whatsoever.

>> With RAII, all resources are treated the same regardless of if
>> they are memory or file handle or sockets or whatever.
>
>Which isn't necessarily an advantage.

Fair enough. It is not an inherant advantage to always treat all
resources the same. If both sides of the interface agree that
different resources are to be treated differently and both sides of
the interface as designed with this understanding, this is perfectly
fine. This works with Java.

However, when you design with RAII, all resources get treated the
same. Any service code that use RAII will encapsulate all resources
and clean up in destructors. This is the way RAII code gets designed.

If the service code gets then used by a client code that use GC,
everything breaks since the client is essentially breaking the
contract.

>> Designing with RAII, your destructor will take care of closing
>> files or freeing memory, everything works fine. RAII is
>> absolutely reliable. As long as all resources are owned by
>> objects and all objects are destroyed, no resources will ever
>> be leaked. Once you introduce GC, you are in trouble because
>> you can't rely on the destructor being run for all objects
>> anymore. It depends, sometimes the destructor will be run,
>> sometimes the finalise will be run, depends, who knows.
>
>No. You know when the destructor will run, and when it won't.

Sorry, maybe I was not clear enough. I am talking from the service
code point of view. A class doesn't know how it will be used so can't
rely anymore on its destructor being run.

Client/User code that creates an object from a class is perfectly
capable of knowing if the destructor will be run or not since it is in
control of deciding to use GC for this object or use deterministic
lifetime management (new or auto).

However, the service/library/class code cannot know and cannot rely on
the destructor always being run anymore. At that point, any class
that clean up in its destructor is broken and should never be used by
a GC client.

So what this mean:

If you write a class that will be used by other code, you must
either:
- Make sure it will never be used by GC client code and then you can
use RAII.
- Not use RAII at all in case it get used by GC client code.
- If you only use memory, you might be OK. Implement the class in a
RAII way but if the class get used by a GC client, hopefully the GC
will also cleanup the memory you used when the destructor does not get
run.

If you write code that use other code, you must know how it was
implemented internally so that you know if you can use GC or if you
can use RAII. To me, this breaks the concepts of encapsulation and
implementation hiding. Unless you *know* that a class only uses
memory as resources, you can't use it in GC but I do not believe that
the user should know how the internal of the class are implemented.

>> The result, IMO, is that the great "benefit" of GC which is to reduce
>> programming complexity by not having to worry about memory management
>> is totally trumped by the newly introduced complexity which is having
>> to implement finalise methods and having to worry about leaking
>> non-memory-only resources due to the destructor not being called.
>
>Actual experience shows otherwise.

I am sorry, maybe the domain we work on are different, maybe its
because for me it is very much normal to use resources other than
memory, maybe its because I have not seen a large application that
uses both RAII and GC at the same time but what I see is added
complexity due to the lack of certainity and the need to know too much
about the other side of the interface.

Yannick

James Kanze

unread,
Nov 3, 2010, 11:24:50 AM11/3/10
to
On Nov 2, 7:15 pm, Öö Tiib <oot...@hot.ee> wrote:
> On Nov 2, 2:40 pm, Keith H Duggar <dug...@alum.mit.edu> wrote:

[...]


> 4) I do not claim that there are lot of cases when raw pointers are
> needed in modern C++. There is huge pile of templated containers and
> the shared_ptr, scoped_ptr, unique_ptr, auto_ptr, intrusive_ptr,
> cow_ptr and just describe it, its there. C++ application with zero raw
> pointers is therefore very possible.

Not really. None of the above smart pointers handle navigation,
for example (the major use of pointers on most of the systems
I have worked on in the past), and none are practical for
graphs.

> 5) Because of 4) GC as core language feature would be waste.

Except for the many applications which have intelligent objects,
and need to navigate between them.

Formally, GC must be a core language feature in order to work;
it places certain constraints on how the compiler can generate
code. (In practice, actual compilers for common architectures
don't violate those constraints, so the Boehm collector works.
Until it doesn't, because some future version of the compiler
violates those constraints.)

--
James Kanze

James Kanze

unread,
Nov 3, 2010, 11:28:43 AM11/3/10
to
On Nov 2, 6:37 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 02/11/2010 18:31, Paavo Helde wrote:

> >> I am the one advocating RAII over garbage collection in
> >> a C++ newsgroup;

No. You're the one who is trying to pretend that the two are
exclusive, when all of the users of GC in C++ I know use both.

> > You don't have to advocate RAII here, I believe most people
> > here are quite fond of C++ RAII. Especially you don't have
> > to advocate RAII *over* GC as there is no inherent reason
> > they should contradict each other or even interfere with
> > each other.

> The problem is that RAII requires destructors to be run; when
> exactly do you run the destructor for a garbage collected
> object?

You are also the one who doesn't bother reading other people's
postings, and prefers to invent strawmen to argue against.

> Unlike memory some resources can not be freed arbitrarily when
> the garbage collector feels like running. If you have to
> explicity call a cleanup method to close resources then why
> bother with a garbage collector at all?

Because it handles one particular problem better than anything
else.

[...]


> My view is that garbage collected C++ sucks, I have yet to be
> convinced of the validity of an alternative view. :)

My view is that your view is nothing but prejudice, unsupported
by any real experience or sound arguments. (At least, you've
not presented any here.)

--
James Kanze

Leigh Johnston

unread,
Nov 3, 2010, 11:37:16 AM11/3/10
to
On 03/11/2010 15:28, James Kanze wrote:
> On Nov 2, 6:37 pm, Leigh Johnston<le...@i42.co.uk> wrote:
>> On 02/11/2010 18:31, Paavo Helde wrote:
>
>>> Leigh Johnston<le...@i42.co.uk> wrote in
>>> news:DdmdnfSagLP4kk3R...@giganews.com:
>
>>>> I am the one advocating RAII over garbage collection in
>>>> a C++ newsgroup;
>
> No. You're the one who is trying to pretend that the two are
> exclusive, when all of the users of GC in C++ I know use both.
>
>>> You don't have to advocate RAII here, I believe most people
>>> here are quite fond of C++ RAII. Especially you don't have
>>> to advocate RAII *over* GC as there is no inherent reason
>>> they should contradict each other or even interfere with
>>> each other.
>
>> The problem is that RAII requires destructors to be run; when
>> exactly do you run the destructor for a garbage collected
>> object?
>
> You are also the one who doesn't bother reading other people's
> postings, and prefers to invent strawmen to argue against.

Try answering my question rather than reverting to trollish bullshit.

>
>> Unlike memory some resources can not be freed arbitrarily when
>> the garbage collector feels like running. If you have to
>> explicity call a cleanup method to close resources then why
>> bother with a garbage collector at all?
>
> Because it handles one particular problem better than anything
> else.

Are you saying that a garbage collector solves the problem of memory
leaks and dangling pointers better than RAII? If so you are deluded.
RAII's determinism trumps garbage collector and doesn't suffer from the
problem of when to free resources other than memory.

>
> [...]
>> My view is that garbage collected C++ sucks, I have yet to be
>> convinced of the validity of an alternative view. :)
>
> My view is that your view is nothing but prejudice, unsupported
> by any real experience or sound arguments. (At least, you've
> not presented any here.)
>

More trollish bullshit.

/Leigh

James Kanze

unread,
Nov 3, 2010, 11:56:23 AM11/3/10
to
On Nov 3, 2:10 pm, ytrem...@nyx.net (Yannick Tremblay) wrote:
> In article
> <9462474b-de0d-4685-89b2-4144bc583...@l17g2000yqe.googlegroups.com>,
> James Kanze <james.ka...@gmail.com> wrote:

[...]


> >> The problem is that garbage collection essentially breaks RAII.

> >That is completely false; the two are completely orthogonal.

> I am afraid I don't see them as such. I can agree that it is
> possible for them to coexist but *completely* orthogonal would
> require them to have no effect on one another whatsoever.

Which is largely the case. RAII depends on object lifetime, by
giving objects specific behavior on their death. GC has nothing
to do with object lifetime.

Perhaps the problem is that GC has been "oversold" by Java
fanatics. Even in Java, you have to deal with lifetime of
object issues.

Another problem, however, is that too many C++ programmers tend
to insist that every object have a deterministic lifetime. Many
don't, and if memory is managed automatically, most don't.
Without memory management, most destructors would be empty.

> >> With RAII, all resources are treated the same regardless of
> >> if they are memory or file handle or sockets or whatever.

> >Which isn't necessarily an advantage.

> Fair enough. It is not an inherant advantage to always treat
> all resources the same. If both sides of the interface agree
> that different resources are to be treated differently and
> both sides of the interface as designed with this
> understanding, this is perfectly fine. This works with Java.
> However, when you design with RAII, all resources get treated
> the same.

Only if you want them to. Memory is very special as a resource,
for a number of reasons.

> Any service code that use RAII will encapsulate all resources
> and clean up in destructors. This is the way RAII code gets
> designed.

RAII doesn't handle all resources. It only handles those whose
lifetime can be easily mapped to a scope, so that the resource
can be freed automatically when that scope ends. This isn't
always, or even often, the case of memory. (If the memory maps
to a scope, you just declare it in that scope, and be done with
it.)

> If the service code gets then used by a client code that use
> GC, everything breaks since the client is essentially breaking
> the contract.

Why? If the contract says that destructors must be called, then
the client code calls the destructor. I don't see where the
problem is there.

Could you give an example? (Just the contract, and perhaps
a short explination of why you think that garbage collection
would break it.)

> >> Designing with RAII, your destructor will take care of closing
> >> files or freeing memory, everything works fine. RAII is
> >> absolutely reliable. As long as all resources are owned by
> >> objects and all objects are destroyed, no resources will ever
> >> be leaked. Once you introduce GC, you are in trouble because
> >> you can't rely on the destructor being run for all objects
> >> anymore. It depends, sometimes the destructor will be run,
> >> sometimes the finalise will be run, depends, who knows.

> >No. You know when the destructor will run, and when it won't.

> Sorry, maybe I was not clear enough. I am talking from the
> service code point of view. A class doesn't know how it will
> be used so can't rely anymore on its destructor being run.

A class certainly should know something about how it will be
used. Something like complex knows that it won't be used to
manage a TCP connection, for example. I'm sure that that's not
what you meant, but I can't figure any other meaning to assign
to those words.

In an application, a class has a role and very specific
responsibilities. In order to perform correctly, it defines
a contract with the client code. For some classes (very few, in
my experience), that contract will require that the client code
"dispose" of them---in C++, we would say call the constructor;
in Java, the class will have a "dispose" function which must be
called, etc. In C++, we have one very big advantage over Java:
if the moment the "dispose" function must be called corresponds
to the moment the object goes out of scope, the compiler will
call the method (the destructor in C++) automatically. If it
doesn't, we still have to call it explicitly (delete operator).

All of this has nothing to do with garbage collection, and
remains unchanged in the presence of garbage collection. With
one big exception: without garbage collection, a lot of classes
which wouldn't otherwise require "dispose", because it's the
last chance they have to free memory. Many (most) of my
classes, for example, have the contract that you must call the
destructor *if* (and only if) there is no garbage collection.

> Client/User code that creates an object from a class is
> perfectly capable of knowing if the destructor will be run or
> not since it is in control of deciding to use GC for this
> object or use deterministic lifetime management (new or auto).

> However, the service/library/class code cannot know and cannot
> rely on the destructor always being run anymore. At that
> point, any class that clean up in its destructor is broken and
> should never be used by a GC client.

No.

What does change, I guess, is that the service must specify the
fact that it must be disposed/destructed as part of its
contract. But that's really the case today anyway, since the
requirement isn't normally just to be destructed "sometime", but
to be destructed in a timely manner (something like scoped_lock,
for example). Which means that some techniques of manual memory
management are excluded as well: you can't, for example, put the
object (or a pointer to the object) in a vector, and only clean
up when there are too many objects in the vector.

> So what this mean:

> If you write a class that will be used by other code, you must
> either:
> - Make sure it will never be used by GC client code and then you can
> use RAII.
> - Not use RAII at all in case it get used by GC client code.
> - If you only use memory, you might be OK. Implement the class in a
> RAII way but if the class get used by a GC client, hopefully the GC
> will also cleanup the memory you used when the destructor does not get
> run.

More specifically, you have to specify a contract, that the
client code has to respect. Nothing new there, and you have to
do that with or without garbage collection.

> If you write code that use other code, you must know how it
> was implemented internally so that you know if you can use GC
> or if you can use RAII. To me, this breaks the concepts of
> encapsulation and implementation hiding. Unless you *know*
> that a class only uses memory as resources, you can't use it
> in GC but I do not believe that the user should know how the
> internal of the class are implemented.

I think you're getting hung up on "resources". Classes have
responsibilities and behavior. Some classes have a very
definite end of lifetime, with specific behavior. Client code
must ensure that this is respected. Garbage collection changes
nothing in all this.

> >> The result, IMO, is that the great "benefit" of GC which is
> >> to reduce programming complexity by not having to worry
> >> about memory management is totally trumped by the newly
> >> introduced complexity which is having to implement finalise
> >> methods and having to worry about leaking non-memory-only
> >> resources due to the destructor not being called.

> >Actual experience shows otherwise.

> I am sorry, maybe the domain we work on are different, maybe
> its because for me it is very much normal to use resources
> other than memory, maybe its because I have not seen a large
> application that uses both RAII and GC at the same time but
> what I see is added complexity due to the lack of certainity
> and the need to know too much about the other side of the
> interface.

Independently of the domain: if the software is well written,
all you need to know about the other side of the interface is
the contract it adhers to. Beyond that, I'm sure that there are
domains where many, or even most, objects do require timely
desposal/destruction, and their lifetimes regularly end at the
end of scope. Even in my applications, there are some:
typically, a Transaction will be allocated on the stack, for
example, and its destructor will effectuate a roll-back if
commit hasn't been called on it. You don't allocate
Transaction's dynamically, and if for some reason you have to
(say because it is to be shared between two asynchronous
threads), then you do use something like shared_ptr.

In typical data servers, and in GUI applications, such objects
are the exception (and having to allocate them dynamically,
rather than on the stack, is even more exceptional). At least
in my experience.

--
James Kanze

Leigh Johnston

unread,
Nov 3, 2010, 12:25:25 PM11/3/10
to

When using both RAII and garbage collection in C++ having to classify
all your classes as either garbage collectable or not garbage
collectable is an unreasonable requirement and has nothing to do with
one's logical program design; it is more an annoying, unnecessary
implementation detail because we irrationally want the memory for
objects which don't own non-memory resources to be reclaimed in a
non-deterministic manner and memory for objects which do own non-memory
resources to be reclaimed in a deterministic manner. IMHO this is
another reason why C++ garbage collection sucks.

If you want to continue being a deluded crazy person you go right ahead.

/Leigh

Ian Collins

unread,
Nov 3, 2010, 3:44:51 PM11/3/10
to
On 11/ 4/10 04:37 AM, Leigh Johnston wrote:
> On 03/11/2010 15:28, James Kanze wrote:
>> On Nov 2, 6:37 pm, Leigh Johnston<le...@i42.co.uk> wrote:
>>
>>> Unlike memory some resources can not be freed arbitrarily when
>>> the garbage collector feels like running. If you have to
>>> explicity call a cleanup method to close resources then why
>>> bother with a garbage collector at all?
>>
>> Because it handles one particular problem better than anything
>> else.
>
> Are you saying that a garbage collector solves the problem of memory
> leaks and dangling pointers better than RAII? If so you are deluded.
> RAII's determinism trumps garbage collector and doesn't suffer from the
> problem of when to free resources other than memory.

There you go again backing up James's straw man comment.

GC does indeed handle one particular problem (closures) better than
anything else. If your code uses them, GC can supplement RAII, it does
not conflict with it.

No one, especially James, has claimed that GC solves the problem of
memory leaks and dangling pointers better than RAII. It is simply
another tool in the box.

--
Ian Collins

Leigh Johnston

unread,
Nov 3, 2010, 4:07:10 PM11/3/10
to

Reposted:

"When using both RAII and garbage collection in C++ having to classify
all your classes as either garbage collectable or not garbage
collectable is an unreasonable requirement and has nothing to do with
one's logical program design; it is more an annoying, unnecessary
implementation detail because we irrationally want the memory for
objects which don't own non-memory resources to be reclaimed in a
non-deterministic manner and memory for objects which do own non-memory
resources to be reclaimed in a deterministic manner. IMHO this is
another reason why C++ garbage collection sucks."

GC does not conflict with RAII *if* you classisfy all your classes as
either garbage collectable or not. GC is not a tool in the standard C++
"box". I was under the impression that this newsgroup was primarily
concerned with *standard* C++.

/Leigh

Matthias Meixner

unread,
Nov 3, 2010, 6:23:49 PM11/3/10
to
Am 02.11.2010 23:23, schrieb Paavo Helde:
>> when exactly
>> do you run the destructor for a garbage collected object?

This is only possible if all objects are handled by the garbage
collector. In a mixed mode system where some objects are handled by GC
and some are not the destructor must be called since the object might
contain pointers to some non-managed objects and these have to be
cleaned up in the destructor.

Matthias Meixner

unread,
Nov 3, 2010, 6:31:17 PM11/3/10
to
Am 03.11.2010 17:25, schrieb Leigh Johnston:
>
> When using both RAII and garbage collection in C++ having to classify
> all your classes as either garbage collectable or not garbage
> collectable is an unreasonable requirement and has nothing to do with
> one's logical program design; it is more an annoying, unnecessary

It is not required to classify _classes_ to be collectable or not as my
garbage collector demonstrates. The decision whether an object is
collectable or not is taken on _allocation_ of the objects. Therefore,
some objects may be handled by the collector whereas other objects of
the _same_ _class_ may be handled manually.

This is the same situation that you have with reference counting: The
objects do not need to know anything about reference counting. This is
the same here just that mark and swipe is used instead of reference
counting.

Leigh Johnston

unread,
Nov 3, 2010, 6:41:58 PM11/3/10
to

Only classes which do not require deterministic destruction (no RAII)
can be *either* collectable or not otherwise you would have to
complicate the class with details of how it is allocated; for this
reason explicit classification would still be required in practice and
would be a pain in the arse. "classification" does not have to involve
any actual code but does require documenting and complicates a design
for anything other than toy/example programs.

/Leigh

Bart van Ingen Schenau

unread,
Nov 4, 2010, 8:40:50 AM11/4/10
to
On Nov 3, 4:56 pm, James Kanze <james.ka...@gmail.com> wrote:
> On Nov 3, 2:10 pm, ytrem...@nyx.net (Yannick Tremblay) wrote:
>
> > In article
> > <9462474b-de0d-4685-89b2-4144bc583...@l17g2000yqe.googlegroups.com>,
> > James Kanze  <james.ka...@gmail.com> wrote:
>
>     [...]
>
> > >> The problem is that garbage collection essentially breaks RAII.
> > >That is completely false; the two are completely orthogonal.
> > I am afraid I don't see them as such.  I can agree that it is
> > possible for them to coexist but *completely* orthogonal would
> > require them to have no effect on one another whatsoever.
>
> Which is largely the case.  RAII depends on object lifetime, by
> giving objects specific behavior on their death.  GC has nothing
> to do with object lifetime.
>
> Perhaps the problem is that GC has been "oversold" by Java
> fanatics.  Even in Java, you have to deal with lifetime of
> object issues.
>
> Another problem, however, is that too many C++ programmers tend
> to insist that every object have a deterministic lifetime.  Many
> don't, and if memory is managed automatically, most don't.
> Without memory management, most destructors would be empty.
>
<snip>

I think that, at least in this discussion, the two sides are not
talking with compatible starting points.
Many C++ developers start with the viewpoint that lifetime management
== memory management.
From the post that I respond to, I get the impression that for you,
James, lifetime management and memory management are not necessarily
connected. And GC is only about memory management and can coexist with
various lifetime management strategies on the objects contained within
that memory.

I can see how RAII and GC can coexist with that viewpoint, because
RAII is primarily about lifetime management (with the added bonus that
it can do memory management as an afterthought) and GC is about memory
management.

My biggest fear for the widespread use of GC is that people get lazy
in their lifetime management of memory-only objects ("what is the big
deal about calling the destructor? The GC will reclaim the memory
anyway."), which breaks horribly if a change to a sub-object (of a sub-
object of a sub-object) makes it an object that also uses non-memory
resources and makes the object require proper lifetime management.
This can have far-reaching ripple effects, in that the entire codebase
may have to be reviewed to ensure lifetime management is properly
applied in all cases where this sub-object is (directly or indirectly)
involved.

> --
> James Kanze

Bart v Ingen Schenau

James Kanze

unread,
Nov 4, 2010, 9:56:46 AM11/4/10
to
On Nov 4, 12:40 pm, Bart van Ingen Schenau <b...@ingen.ddns.info>
wrote:

> On Nov 3, 4:56 pm, James Kanze <james.ka...@gmail.com> wrote:

[...]


> I think that, at least in this discussion, the two sides are not
> talking with compatible starting points.
> Many C++ developers start with the viewpoint that lifetime management
> == memory management.
> From the post that I respond to, I get the impression that for you,
> James, lifetime management and memory management are not necessarily
> connected. And GC is only about memory management and can coexist with
> various lifetime management strategies on the objects contained within
> that memory.

Exactly. That is my point. Memory management is distinct from
lifetime, in an absolute sense: the memory underlying an object
can continue to exist, and even be accessible as raw memory,
after the lifetime of an object has finished. The C++ standard
makes this distinction, but far to many programmers confound it.

> I can see how RAII and GC can coexist with that viewpoint, because
> RAII is primarily about lifetime management (with the added bonus that
> it can do memory management as an afterthought) and GC is about memory
> management.

> My biggest fear for the widespread use of GC is that people get lazy
> in their lifetime management of memory-only objects ("what is the big
> deal about calling the destructor?

That is a real problem. It happens a lot in Java, for example.
But in my experience, such people are also careless about their
lifetime management without garbage collection.

> The GC will reclaim the memory anyway."), which breaks
> horribly if a change to a sub-object (of a sub- object of
> a sub-object) makes it an object that also uses non-memory
> resources and makes the object require proper lifetime
> management.

This is a common objection, but I've yet to find a realistic
situation where it might occur. You can't just replace one
object type with another in code, without considering the
contract of the object in question.

> This can have far-reaching ripple effects, in that the entire codebase
> may have to be reviewed to ensure lifetime management is properly
> applied in all cases where this sub-object is (directly or indirectly)
> involved.

Some review would possibly be in order (although the situation
is not nearly as bad as when exceptions where introduced). In
fact, I don't recommend introducing garbage in working projects;
it's more something you should adopt when starting new projects.

--
James Kanze

Leigh Johnston

unread,
Nov 4, 2010, 10:28:41 AM11/4/10
to

Yes that is my worry, that you introduce garbage in working projects as
well as newsgroups.

/Leigh

Miles Bader

unread,
Nov 6, 2010, 8:33:40 PM11/6/10
to
James Kanze <james...@gmail.com> writes:
>> The GC will reclaim the memory anyway."), which breaks
>> horribly if a change to a sub-object (of a sub- object of
>> a sub-object) makes it an object that also uses non-memory
>> resources and makes the object require proper lifetime
>> management.
>
> This is a common objection, but I've yet to find a realistic
> situation where it might occur. You can't just replace one
> object type with another in code, without considering the
> contract of the object in question.

I've only been following this thread occasionally[*], but the whole
"don't call the constructor" position seems kind of absurd; even if you
only care about memory, surely non-gc-allocated memory resources are
common in C++, especially given an allocator like this that seems to
offer free mixing of allocation styles, and those will only be freed
properly if you run the constructor.

E.g., you use your "GC" allocator to allocate instances of X (cause in
your proggie it's annoying to track them), but X happens to use
std::vector for one of its fields...

-Miles


[*] 'cause it seems to have resulted in even more fanboy wanking than is
usual for c.l.c++ (I'd not have thought that's possible, but ...)

--
You can hack anything you want, with TECO and DDT.

James Kanze

unread,
Nov 7, 2010, 9:46:32 AM11/7/10
to
On Nov 7, 12:33 am, Miles Bader <mi...@gnu.org> wrote:

[...]


> I've only been following this thread occasionally[*], but the whole
> "don't call the constructor" position seems kind of absurd; even if you
> only care about memory, surely non-gc-allocated memory resources are
> common in C++,

Are they? In the programs I've worked on, they've been rather
rare, and in all cases, managed by special classes, which are
used in clearly delimited circumstances.

> especially given an allocator like this that seems to offer
> free mixing of allocation styles, and those will only be freed
> properly if you run the constructor.

(I think by "constructor", you actually mean the destructor.
Constructors are always run.)

> E.g., you use your "GC" allocator to allocate instances of X
> (cause in your proggie it's annoying to track them), but X
> happens to use std::vector for one of its fields...

I would not recommend a system where only some of the memory is
managed by the garbage collector. And the only resource
std::vector uses is memory, so there should be no problem
collecting objects which contain std::vector.

--
James Kanze

Miles Bader

unread,
Nov 7, 2010, 6:26:22 PM11/7/10
to
James Kanze <james...@gmail.com> writes:
>> I've only been following this thread occasionally[*], but the whole
>> "don't call the constructor" position seems kind of absurd; even if you
>> only care about memory, surely non-gc-allocated memory resources are
>> common in C++,
>
> Are they? In the programs I've worked on, they've been rather
> rare, and in all cases, managed by special classes, which are
> used in clearly delimited circumstances.

Er, they're the _standard_ in normal C++... you know, what, "new Foo"
does... (what are you thinking of?)

>> especially given an allocator like this that seems to offer
>> free mixing of allocation styles, and those will only be freed
>> properly if you run the constructor.
>
> (I think by "constructor", you actually mean the destructor.
> Constructors are always run.)

Yes, thanks, I meant "destructor."

>> E.g., you use your "GC" allocator to allocate instances of X
>> (cause in your proggie it's annoying to track them), but X
>> happens to use std::vector for one of its fields...
>
> I would not recommend a system where only some of the memory is
> managed by the garbage collector.

Why? Providing you run destructors from the GC, the additional memory
will be freed in either case. The GC won't have as much information as
a traditional all-or-nothing GC (it won't know about "secondary" outside
allocation), but presumably the user (of the GC) knows about this, and
the GC parameters reflect it.

[Anyway, "I would not recommend" is not an argument, of course...]

> And the only resource
> std::vector uses is memory, so there should be no problem
> collecting objects which contain std::vector.

Yeah, but the point is that std::vector does its own allocations, which
don't automatically use the same allocator as the enclosing object.

So in order to avoid intrusive source modifications, it's convenient if
secondary allocations are handled transparently -- which they are, of
course, as long as you run the destructor...

-Miles

--
Occam's razor split hairs so well, I bought the whole argument!

Keith H Duggar

unread,
Nov 18, 2010, 9:49:07 AM11/18/10
to

Great, you are aware of (at least some) of the issues. Then one
must wonder why you would pose such a naive question as "What is
so bad about [zombie states]?". Since clearly there are many bad
things about them and the issues involved are complex. Perhaps
that is why noone has yet proposed a fully consistent model for
combining C++ style deterministic destruction with GC.

> 1) No one argues with the fact that GC adds well-defined and
> detectable corpse state for detecting dangling raw pointer
> dereference.

And nobody argues that such zombie states introduce considerable
complexity into the language model /especially/ if, as you say
above, it is a "detectable" at the language level.

> 2) I do not argue that it is far from what is GC in C# or Java.
> Call it something else I don't care.

And where is the implementation of your imaginary "call it something
else" system? Where is the specification? The language model?

> 10) People who are making money by consulting and training C++ (like
> Dave Abrahams) certainly love that C++ is such a pile of gotchas and
> undefined behaviors from top to bottom. People who write software have
> not entirely overlapping goals with them.

Fortunately we don't need to rely on bogus ad hominem arguments
such as above. Their /logic/ and reasoning are widely available
for anyone to /logically/ dispute.

KHD

PS. For those out there who ignorantly think ad hominem == insult,
Oo's point 10) above is a perfect example of an /actual/ ad hominem
argument. Personal attacks, insults, cursing, etc are usually /not/
ad hominem. They are usually just crap.

Rather, ad hominem is arguing that one should not believe the
arguments of a person because of personal qualities. In the example
above Oo argues one should dismiss Dave Abrahams (a highly logical,
intelligent man who expresses his points with exceptional clarity)
because he is a C++ consultant ... lmao.

Please learn this concept. It's just so dumb when somebody jumps
on any personal attack as "ad hominem". Total ignorance of logic.

Öö Tiib

unread,
Nov 18, 2010, 4:03:11 PM11/18/10
to

Perhaps you took my question out of context and so classified me
extreme naive. What i meant was that "destroyed" state is better than
"destroyed and reused for something else by underlying memory
management" state. So ... if GC guarantees no reuse for memory under
destroyed but still pointed at objects then i do not see why it is
bad?

>
> > 1) No one argues with the fact that GC adds well-defined and
> > detectable corpse state for detecting dangling raw pointer
> > dereference.
>
> And nobody argues that such zombie states introduce considerable
> complexity into the language model /especially/ if, as you say
> above, it is a "detectable" at the language level.

Complexity around these zombies is far worse currently. Reading
destroyed objects goes without any way to detect it on lot of
implementations. Writing into not yet reused memory can be detected,
but with special debugging options. Writing into already reused memory
is again totally undetectable with most implementations. If language
for example guarantees anything there about dangling pointer (thanks
to GC) then how it can be worse or more complex?

> > 2) I do not argue that it is far from what is GC in C# or Java.
> > Call it something else I don't care.
>
> And where is the implementation of your imaginary "call it something
> else" system? Where is the specification? The language model?

I understand your question like "How can language engine help?" If i
misunderstand please clarify. I have tried that Boehm garbage
collector and it sort of ... worked well. It was like in the GC
languages, only that it did not have finalizers. I had to destroy
things to get the destructors called, but that GC did not forbid
explicit destruction and deallocation so normal C++ worked OK. The
finalizers are something i actually do not find desirable. The issues
with what the language could help that i saw:

1) Garbage collection scales well (better than without in some tests).
For gaining even better performance from using GC the code has to be
tuned/optimized for garbage collection. Implementations can help
there.

2) For gaining additional security with pointers, some manual work has
to be done (these can be implemented as std templates, language
elements and features of GC).

3) Garbage collector can naturally detect leaks. On most cases quite
soon after these did happen. So it is powerful tool to detect leaks of
non-memory resources. The way to mark objects as holders of such
resources is missing from language.

> > 10) People who are making money by consulting and training C++ (like
> > Dave Abrahams) certainly love that C++ is such a pile of gotchas and
> > undefined behaviors from top to bottom. People who write software have
> > not entirely overlapping goals with them.
>
> Fortunately we don't need to rely on bogus ad hominem arguments
> such as above. Their /logic/ and reasoning are widely available
> for anyone to /logically/ dispute.

Yes, you are correct. I love C++ as flexible, elegant and powerful
language, but lot of things in it are clearly too undefined or freaky
(bad). Experienced know their ways there, less experienced can do hard-
to-detect damage and it is hard to teach how not to on cases. Dave
Abrahams is good specialist, intelligent and well respected, but for
some reason he wants that one of the worst parts will stay bad. So my
ad hominem argument was trying to give a reason why he is so negative
there.

Bjarne Stroustrup has always been positive when discussing garbage
collection. I read from somewhere few years ago that he does hope to
see (at least optional) garbage collection as part of C++0x. While
original architect of anything can be wrong at some spot, this is not
one of such cases IMHO.

0 new messages