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

Experience with real world C/C++ projects that used GC?

7 views
Skip to first unread message

Pavel Vozenilek

unread,
Mar 22, 2006, 6:44:52 PM3/22/06
to
Garbage collection is around for decades.
Surely it must have been tried in C or C++ projects.

What experience has been gathered on such projects?
Does anyone know links, studies, war stories,
post-mortems, recommendations etc?

This information would be very useful complement to
current GC related discussions.

/Pavel

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

peter koch larsen

unread,
Mar 23, 2006, 6:30:51 AM3/23/06
to

Pavel Vozenilek wrote:
> Garbage collection is around for decades.
> Surely it must have been tried in C or C++ projects.
>
> What experience has been gathered on such projects?
> Does anyone know links, studies, war stories,
> post-mortems, recommendations etc?
>
> This information would be very useful complement to
> current GC related discussions.
>
> /Pavel

I'd like to backup this initiative. I would also like to hear what is
missing in the current approach - e.g. using the Boehm collector. What
features are missing? What could be done in order to improve
performance further? In short: what is the motivation for the current
proposals for building in garbage collections into C++?

Kind regards
Peter

Pavel Vozenilek

unread,
Mar 24, 2006, 7:48:14 AM3/24/06
to

"peter koch larsen" wrote:

> I would also like to hear what is
> missing in the current approach - e.g. using the Boehm collector. What
> features are missing? What could be done in order to improve
> performance further?
>


These things may help
(guess, I did not use Boehm GC):

a) application wide type traits that say
"instances of this class do not contain pointers"
and
"pointers to instances of this class point only to the beginning"

so the burden on the collector would be reduced.
This trait would need to became semi-standard.

b) STL, iostreams written in GC in mind, using the traits above

c) Boost and other popular libraries updated to
use the traits above.


I really think someone must have tried to go this way
for a large C++ project.

/Pavel

Pavel Vozenilek

unread,
Mar 24, 2006, 10:57:39 AM3/24/06
to

"Pavel Vozenilek" wrote:

> Garbage collection is around for decades.
> Surely it must have been tried in C or C++ projects.
>
> What experience has been gathered on such projects?
> Does anyone know links, studies, war stories,
> post-mortems, recommendations etc?
>

To answer myself: this question has been asked
few times on Usenet and got either
no or evasive answer.

Several people hinted that GC is used in commercial/custom C++
projects but no technical details were given (not even size of the project).

Searching the web was no different: just a few projects mention
use of GC and it is sometimes for experimental purpose.
Pages describing GC implementations do not provide list of applications.


An informative paper comparing 5 different allocators, including
Boehm collector (from 1993) can be found at:
http://citeseer.ist.psu.edu/detlefs93memory.html

On the other hand, /very many/ discussions about GC
had been started, the most sucessful ones gathering
hundredths of posts.

/Pavel

PS: I may have missed the information I looked for,
the amount of GC advocacy and emotional opinions
is dwarfing everything else.

Jerry Coffin

unread,
Mar 24, 2006, 11:11:27 AM3/24/06
to
In article <1143105500.471400.66840
@e56g2000cwe.googlegroups.com>,
peter.ko...@gmail.com says...

[ ... ]

> I'd like to backup this initiative. I would also like to hear what is
> missing in the current approach - e.g. using the Boehm collector. What
> features are missing? What could be done in order to improve
> performance further? In short: what is the motivation for the current
> proposals for building in garbage collections into C++?

The first and biggest feature missing is working
correctly with all well-defined C++ code. All of the
tricks that have been mentioned that hide pointers can
make it produce incorrect results (i.e. treat data as
garbage prematurely). OTOH, nearly the only solution to
most of these problems is to simply make the behavior
undefined if you use them.

The reason I've discussed copying collectors is that
they're generally much more efficient than mark/sweep
collectors. With a copying collector, an allocation is
normally almost equivalent to allocating space on the
stack.

I've already suggested wording that I believe handles
most of what is necessary for a mark-sweep collector. The
original intent was to support copying collectors as
well, but the issue that's been raised with hashing
pointers requires a bit more work to deal with.

--
Later,
Jerry.

The universe is a figment of its own imagination.

n2xssvv g02gfr12930

unread,
Mar 24, 2006, 11:23:26 AM3/24/06
to
Pavel Vozenilek wrote:
> Garbage collection is around for decades.
> Surely it must have been tried in C or C++ projects.
>
> What experience has been gathered on such projects?
> Does anyone know links, studies, war stories,
> post-mortems, recommendations etc?
>
> This information would be very useful complement to
> current GC related discussions.
>
> /Pavel

Personally, I use STL containers, or carefully created and tested
classes. These then automatically do any garbage collection when they go
out of scope and call the destructor. In my experience if any garbage
collection is not made automatic, the code is much more susceptible to
garbage collection bugs, especially if it uses exception handling.

JB

Hyman Rosen

unread,
Mar 24, 2006, 12:12:46 PM3/24/06
to
Pavel Vozenilek wrote:
> To answer myself: this question has been asked
> few times on Usenet and got either
> no or evasive answer.

GCC uses garbage collection internally. Go look at
their mailing lists at <http://gcc.gnu.org/ml/gcc/>
and search for garbage collection.

loufoque

unread,
Mar 25, 2006, 5:56:54 AM3/25/06
to
n2xssvv g02gfr12930 wrote :

> Personally, I use STL containers, or carefully created and tested
> classes. These then automatically do any garbage collection when they go
> out of scope and call the destructor.

This is RAII, which is a deterministic behaviour, and not garbage
collection.
With garbage collection you can't really predict when the garbage will
be freed.

(Feel free to correct me if I'm wrong)

Francis Glassborow

unread,
Mar 25, 2006, 7:04:50 PM3/25/06
to
In article <44243665$0$7811$636a...@news.free.fr>, loufoque
<louf...@remove.gmail.com> writes

>n2xssvv g02gfr12930 wrote :
>
>> Personally, I use STL containers, or carefully created and tested
>> classes. These then automatically do any garbage collection when they go
>> out of scope and call the destructor.
>
>This is RAII, which is a deterministic behaviour, and not garbage
>collection.
>With garbage collection you can't really predict when the garbage will
>be freed.
>
>(Feel free to correct me if I'm wrong)

In a sense you are right. I think the issue is really about manual
versus automatic memory management. Both GC and RAII + smart pointers
address issues of automating memory management. The latter also address
issues of management of other resources and of object lifetimes. However
GC still has something to offer even when RAII etc. is in use.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

skaller

unread,
Mar 26, 2006, 7:52:18 AM3/26/06
to
On Wed, 22 Mar 2006 18:44:52 -0500, Pavel Vozenilek wrote:

> Garbage collection is around for decades.
> Surely it must have been tried in C or C++ projects.
>
> What experience has been gathered on such projects?
> Does anyone know links, studies, war stories,
> post-mortems, recommendations etc?
>
> This information would be very useful complement to
> current GC related discussions.

Felix

http://felix.sf.net

uses an exact garbage collector in conjunction with a compiler
to generate C++. The compiler generates shape (RTTI) objects
which tell the collector where the pointer are.

The compiler is a whole program analyser, and is able to
optimise so that only needed RTTI objects are generated.
Typically, this is only required for variant types
and closures stored in variables.

The default collector is naive sweep, which is probably
the best kind for C++. It allows manual deletion, and only
collects particular objects -- others remain managed by RAII
and manual deletion. This is similar in some ways to
Microsoft's "managed C++" language I think.

The collector is thread safe, slow, has high overhead,
and can only be invoked from procedural code.

However it is probably faster than any kind of advanced
collector. As Stroustrup once said: C++ spawns small numbers
of large mutable heap objects, where functional languages spawn
large number of small immutable objects.

In Felix this is very much so: since it inlines very heavily
many functions just disappear. Typical 'functional' C like
routines reduce to those same C routines, and the machine
stack is used for storage.

The collector also has optional compaction with an arena
allocator. It turned out in some tests I did that the code,
which basically adds a pointer to an offset, and checks for
overflow .. is actually slower than malloc.

The major difficulty with such a hybrid is that we need to
re-implement data structures: STL is supported and works fine
with C++ data structures but it can't be used with managed
objects.

On the other hand, STL is not very useful in C++ because
the C++ language fails to provide lexically scoped closures,
variants, type recursion, and other features actually needed
in any decent programming language, and once you make the
language more advanced as is done in Felix, there are other ways to
manage data structures than by using STL style iterators,
for example using folds and maps specialised for the data structure.
The loss of control inversion here is no problem in Felix since
it control inverts procedural code automatically, and provides
synchronous thread/channels for user level inversion.

The upshot is you can use legacy C++ code fine, since it
doesn't need collection. And you can write new Felix code
using legacy C++ libraries, provided you don't use managed
objects. Finally you can use managed objects, and allow
the system to manage them for you -- in many cases knowing
the compiler will optimise away any need for garbage
collection.

Finally, for many jobs -- such as a server -- the job is naturally
partitioned into independent threads, and Felix allows each
to have its own collector. This reduces over-all collection
time, as well as eliminating stop-the-world freezing.

--
John Skaller <skaller at users dot sf dot net>
Try Felix, the successor to C++ http://felix.sf.net

Mirek Fidler

unread,
Mar 26, 2006, 7:53:12 AM3/26/06
to
> GCC uses garbage collection internally. Go look at
> their mailing lists at <http://gcc.gnu.org/ml/gcc/>
> and search for garbage collection.

I believe GCC is plain C, not C++, is not it?

Mirek

Pavel Vozenilek

unread,
Mar 26, 2006, 12:49:00 PM3/26/06
to

"Mirek Fidler"write:

>> GCC uses garbage collection internally. Go look at
>> their mailing lists at <http://gcc.gnu.org/ml/gcc/>
>> and search for garbage collection.
>
> I believe GCC is plain C, not C++, is not it?
>

GCC is written in C and uses customized garbage collector
http://gcc.gnu.org/ml/gcc/2001-07/msg02025.html
which is:

- is type-accurate;
- requires explicit manual registration of any global variables
that might contain pointers to the GC'd heap; and
- collects only when you explicitly invoke ggc_garbage_collect()
(which in most cases means you don't need to explicitly
register stuff on the stack).

The Boehm collector is used by the Java runtime.

/Pavel

PS: Btw, what's your experience with OCG2?

Jeffrey Schwab

unread,
Mar 26, 2006, 12:50:29 PM3/26/06
to
Mirek Fidler wrote:
>> GCC uses garbage collection internally. Go look at
>> their mailing lists at <http://gcc.gnu.org/ml/gcc/>
>> and search for garbage collection.
>
> I believe GCC is plain C, not C++, is not it?

Lowercase gcc is the Gnu C Compiler. Uppercase GCC is the GNU Compiler
Collection, which includes gcc, g++, and some compilers (e.g. gcj) of
garbage-collected languages.

Mirek Fidler

unread,
Mar 26, 2006, 3:15:07 PM3/26/06
to
Jeffrey Schwab wrote:
> Mirek Fidler wrote:
>
>>> GCC uses garbage collection internally. Go look at
>>> their mailing lists at <http://gcc.gnu.org/ml/gcc/>
>>> and search for garbage collection.
>>
>> I believe GCC is plain C, not C++, is not it?
>
>
> Lowercase gcc is the Gnu C Compiler. Uppercase GCC is the GNU
> Compiler
> Collection, which includes gcc, g++, and some compilers (e.g. gcj) of
> garbage-collected languages.

Sorry for fuzzy comment, I meant, GCC is written in plain C, so its
usage of GC is less important for this thread (then again, maybe it is
not...).

Mirek

James Dennett

unread,
Mar 27, 2006, 9:25:26 AM3/27/06
to
Jeffrey Schwab wrote:
> Mirek Fidler wrote:
>>> GCC uses garbage collection internally. Go look at
>>> their mailing lists at <http://gcc.gnu.org/ml/gcc/>
>>> and search for garbage collection.
>> I believe GCC is plain C, not C++, is not it?
>
> Lowercase gcc is the Gnu C Compiler. Uppercase GCC is the GNU
> Compiler
> Collection, which includes gcc, g++, and some compilers (e.g. gcj) of
> garbage-collected languages.

GCC's C and C++ compilers are implemented in C, which
might be what "I believe GCC is plain C, not C++, is
not it?" was referring to.

(GCC's Ada compiler is written in Ada, which gives rise
to different bootstrapping issues, and ISTR that there
have been efforts to make GCC's C and C++ compilers
compile as C++ as well as C, with numerous bugs being
uncovered that way.)

GCC's C++ compiler is an example of C with garbage
collection, rather than C++ with garbage collection.

-- James

Nemanja Trifunovic

unread,
Mar 27, 2006, 9:44:24 AM3/27/06
to

Hyman Rosen wrote:
> Pavel Vozenilek wrote:
>> To answer myself: this question has been asked
>> few times on Usenet and got either
>> no or evasive answer.
>
> GCC uses garbage collection internally.

And GCC is not exactly the fastest compiler I have tried. Not that I
take it as a proof that GC is slow, but the correlation seems to be
stronger and stronger as soon as we move from benchmarks to real world
applications..

Allan W

unread,
Mar 27, 2006, 5:26:10 PM3/27/06
to
Pavel Vozenilek wrote:
> a) application wide type traits that say
> "instances of this class do not contain pointers"

I can see how this would be very useful, if GC was implemented
in the compiler (and not just in the library).

> and
> "pointers to instances of this class point only to the
> beginning"

On the other hand, even if this one was useful (and I haven't really
thought it out yet), it seems to me that it would be nearly synonymous
with, "this class is not stored in a container or array." (Arrays and
most containers allocate enough memory for N copies of the
contained class, where 1 <= N <= capacity.)

The problem is, putting this definition on the class itself is the
wrong place for it... Surely when you design a class such as
Customer you're not thinking about the containers!

You'd basically have two choices: Mostly stop using containers, or
mostly don't mark ANY classes with this attribute.

Maybe an alternative would be an attribute on pointers:
"This pointer points only to the first allocated byte." In other
words, it points to an instance allocated directly by (non-
placement) new T, or new Something-derived-from-T (or
equivalents such as malloc + placement new).

Some people have wanted this attribute for a long time
anyway. It would help to catch code such as

// Bug waiting -- p1 points to an array, so the static
// type ought to match the dynamic type
Customer *p1 = new SpecialCustomer[3];
// If sizeof(SpecialCustomer)>sizeof(Customer), then
std::cout << p1[1]; // will crash -- but no compiler warning

// Bug waiting -- p2 points to a single instance,
// so pointer math shouldn't be used
Customer *p2 = new Customer;
std::cout << p2[1]; // This ALWAYS crashes --
// but no compiler warning

Separating pointer-to-instance from pointer-to-array
would be a great help -- at the expense of breaking
80% or more of existing programs. (Is that too
expensive? Why? :-)

kanze

unread,
Mar 28, 2006, 10:05:11 AM3/28/06
to
Nemanja Trifunovic wrote:
> Hyman Rosen wrote:
>> Pavel Vozenilek wrote:
>>> To answer myself: this question has been asked
>>> few times on Usenet and got either
>>> no or evasive answer.

>> GCC uses garbage collection internally.

> And GCC is not exactly the fastest compiler I have tried. Not
> that I take it as a proof that GC is slow, but the correlation
> seems to be stronger and stronger as soon as we move from
> benchmarks to real world applications..

It's not the slowest, either. And I think you'll find that most
of the speed penalty it takes is due to its being generic.
Supporting multiple languages for multiple platforms isn't free.
(Another reason the C++ compiler might be slow is that it
implements full two-phase look-up. I've noticed a lot of C++
compilers slowing down as they introduce full support for
templates.)

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

jlin...@hotmail.com

unread,
Mar 28, 2006, 5:52:39 PM3/28/06
to
kanze wrote:

> It's not the slowest, either. And I think you'll find that most
> of the speed penalty it takes is due to its being generic.
> Supporting multiple languages for multiple platforms isn't free.
> (Another reason the C++ compiler might be slow is that it
> implements full two-phase look-up. I've noticed a lot of C++
> compilers slowing down as they introduce full support for
> templates.)
>
> --

Which compilers do you find are slower? On Windows I've used a number
(Intel, Metrowerks, Microsoft, Borland) and gcc really is exceptionally
slow... And on top of that the executables it produces are
substantially less optimized. It's hardly a poster boy for garbage
collection.

I wince every time I need to do a release build with gcc.

And on a side note, I think it's telling how few responses there have
been to this thread. Relating some practical experiences would IMO
yield a lot more progress than endless opining on the theoretical
aspects of GC.

Jarl.

Mirek Fidler

unread,
Mar 29, 2006, 5:56:35 AM3/29/06
to
Nemanja Trifunovic wrote:
> Hyman Rosen wrote:
>
>>Pavel Vozenilek wrote:
>>
>>>To answer myself: this question has been asked
>>>few times on Usenet and got either
>>>no or evasive answer.
>>
>>GCC uses garbage collection internally.
>
>
> And GCC is not exactly the fastest compiler I have tried. Not that I
> take it as a proof that GC is slow, but the correlation seems to be
> stronger and stronger as soon as we move from benchmarks to real world
> applications..

I believe that it has something to do with allocation pattern and total
amount of data app has to handle.

If application creates a lot of temporary objects, but has a little of
"permanent" data, garbage collection can be a win. I think many of those
benchmarks fail to this categhory.

If your dataset grows significantly, GC will have to spend more and more
time in mark phase and performance will inevitable go down.

Mirek

Pavel Vozenilek

unread,
Mar 29, 2006, 5:56:05 AM3/29/06
to

"Allan W" wrote:

> Pavel Vozenilek wrote:
>> a) application wide type traits that say
>> "instances of this class do not contain pointers"
>
> I can see how this would be very useful, if GC was implemented
> in the compiler (and not just in the library).
>
>> and
>> "pointers to instances of this class point only to the
>> beginning"
>
> On the other hand, even if this one was useful (and I haven't really
> thought it out yet), it seems to me that it would be nearly synonymous
> with, "this class is not stored in a container or array." (Arrays and
> most containers allocate enough memory for N copies of the
> contained class, where 1 <= N <= capacity.)
>

Boehm collector may employ both of the features
to reduce scanning.


> The problem is, putting this definition on the class itself is the
> wrong place for it... Surely when you design a class such as
> Customer you're not thinking about the containers!
>

Next standard change is in 2008, maybe.


> // Bug waiting -- p1 points to an array, so the static
> // type ought to match the dynamic type
> Customer *p1 = new SpecialCustomer[3];
> // If sizeof(SpecialCustomer)>sizeof(Customer), then
> std::cout << p1[1]; // will crash -- but no compiler warning
>
> // Bug waiting -- p2 points to a single instance,
> // so pointer math shouldn't be used
> Customer *p2 = new Customer;
> std::cout << p2[1]; // This ALWAYS crashes --
> // but no compiler warning
>
> Separating pointer-to-instance from pointer-to-array
> would be a great help -- at the expense of breaking
> 80% or more of existing programs. (Is that too
> expensive? Why? :-)
>

Hmm, some mistakes like this may be possibly caught
by a very advanced static analysis.

/Pavel

kanze

unread,
Mar 29, 2006, 5:50:24 AM3/29/06
to
Allan W wrote:
> Pavel Vozenilek wrote:
> > a) application wide type traits that say
> > "instances of this class do not contain pointers"

> I can see how this would be very useful, if GC was implemented
> in the compiler (and not just in the library).

> > and
> > "pointers to instances of this class point only to the
> > beginning"

> On the other hand, even if this one was useful (and I haven't
> really thought it out yet), it seems to me that it would be
> nearly synonymous with, "this class is not stored in a
> container or array." (Arrays and most containers allocate
> enough memory for N copies of the contained class, where 1 <=
> N <= capacity.)

> The problem is, putting this definition on the class itself is
> the wrong place for it... Surely when you design a class such
> as Customer you're not thinking about the containers!

Yes and no. Given the way C++ works, you can't store
polymorphic items in an array. You could certainly put this
attribute on any abstract class, for example.

The real problem with it is that you, as programmer, don't know
when it is true or not (at least as it was originally
formulated). There is no guarantee that a pointer to base
points to the first byte of the object, and there are cases
(multiple inheritance) where it almost certainly doesn't.

> You'd basically have two choices: Mostly stop using
> containers, or mostly don't mark ANY classes with this
> attribute.

Sort of. Most of my classes can be categorized as either entity
objects or value objects. Entity objects are usually
polymorphic, and are never in arrays (although pointers to them
might be). Value objects are almost never dynamically
allocated. Given your formulation, it would be simple to
annotate the classes. But totally useless, since generally, all
I'll have is pointers to the base class, and who knows whether
that's the first byte or not. Given his formulation, any
annotation would be impossible, since I don't know the answer
for entity objects, and almost by definition, value objects may
end up in arrays.

> Maybe an alternative would be an attribute on pointers: "This
> pointer points only to the first allocated byte." In other
> words, it points to an instance allocated directly by (non-
> placement) new T, or new Something-derived-from-T (or
> equivalents such as malloc + placement new).

But how do you know. As soon as you convert to Base*, you don't
know.

> Some people have wanted this attribute for a long time anyway.
> It would help to catch code such as

> // Bug waiting -- p1 points to an array, so the static
> // type ought to match the dynamic type
> Customer *p1 = new SpecialCustomer[3];
> // If sizeof(SpecialCustomer)>sizeof(Customer), then
> std::cout << p1[1]; // will crash -- but no compiler warning

> // Bug waiting -- p2 points to a single instance,
> // so pointer math shouldn't be used
> Customer *p2 = new Customer;
> std::cout << p2[1]; // This ALWAYS crashes --
> // but no compiler warning

> Separating pointer-to-instance from pointer-to-array would be
> a great help -- at the expense of breaking 80% or more of
> existing programs. (Is that too expensive? Why? :-)

I'm not sure about the number of programs it would break. I
don't think I've ever used array new, in 15 years of C++.
Today, I use std::vector, and in pre-standard times, I had my
own array class, which also separated allocation and
initialization, for more or less the same reasons std::vector
does.

What we probably should do is simply get rid of array new
completely. Except that while there aren't many cases where you
need it, when you do need it, you need it.

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

Nemanja Trifunovic

unread,
Mar 29, 2006, 7:02:40 AM3/29/06
to

kanze wrote:

> (Another reason the C++ compiler might be slow is that it
> implements full two-phase look-up. I've noticed a lot of C++
> compilers slowing down as they introduce full support for
> templates.)
>

If I remember correctly, two-phase name lookup was introduced with GCC
3.4. It was definitely slow in earlier versions.

Back to the point - I am sure that reasons other than GC can be found,
but still have to see a "GC" application that performes well compared
to similar "non-GC" ones.

kanze

unread,
Mar 29, 2006, 11:00:28 AM3/29/06
to
jlin...@hotmail.com wrote:
> kanze wrote:

> > It's not the slowest, either. And I think you'll find that
> > most of the speed penalty it takes is due to its being
> > generic. Supporting multiple languages for multiple
> > platforms isn't free. (Another reason the C++ compiler
> > might be slow is that it implements full two-phase look-up.
> > I've noticed a lot of C++ compilers slowing down as they
> > introduce full support for templates.)

> Which compilers do you find are slower?

Not necessarily slower, but Sun CC is about the same speed. And
the version of it that I'm using (5.5) doesn't support
everything in templates -- I don't think it supports two phased
lookup.

Back when g++ didn't support two phased lookup, it was a lot,
lot faster than Sun CC. (On the other hand, it didn't have the
standard iostream, so including <iostream.h> didn't involve any
template processing. And THAT makes a significant difference.)

> On Windows I've used a number (Intel, Metrowerks, Microsoft,
> Borland) and gcc really is exceptionally slow...

The only compiler I've used under Windows is VC++ (and only a
very little), so I cannot say. Compilation under Windows with
VC++ takes me more time than compilation using g++ under Linux,
but since they run on different machines, that doesn't mean
anything.

> And on top of that the executables it produces are
> substantially less optimized. It's hardly a poster boy for
> garbage collection.

You do have to compare things which are comparable. A portable
compiler will never be as fast as one designed for a single
platform (nor will it optimize as well). A fully conformant
compiler will probably be slower than one which cuts corners as
well -- things like two-phase lookup can be very expensive in
compile time. My impression, compared with other compilers, is
that it actually does a surprisingly good job, both in terms of
compile speeds and optimization.

> I wince every time I need to do a release build with gcc.

> And on a side note, I think it's telling how few responses
> there have been to this thread. Relating some practical
> experiences would IMO yield a lot more progress than endless
> opining on the theoretical aspects of GC.

That's probably because the question was an obvious troll.
There's so much literature available on the network that it
seems obvious that anyone who isn't aware of major projects
using GC doesn't want to be aware. The "my mind's made up,
don't confuse me with the facts" syndrome.

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

Mirek Fidler

unread,
Mar 30, 2006, 2:43:33 AM3/30/06
to
> You do have to compare things which are comparable. A portable
> compiler will never be as fast as one designed for a single
> platform (nor will it optimize as well).

Well, while this sounds very "wise", in reality I do not see any
practical reason why well designed C++ compiler should be slow because
it is "portable".

> There's so much literature available on the network that it
> seems obvious that anyone who isn't aware of major projects
> using GC doesn't want to be aware. The "my mind's made up,
> don't confuse me with the facts" syndrome.

Actually, maybe original poster just wanted to be pointed in the right
direction.

Google "major C++ projects using garbage collection" does not yield
anything useful in the first 50 hits.

Mirek

jlin...@hotmail.com

unread,
Mar 30, 2006, 7:26:50 AM3/30/06
to

kanze wrote:
>
> > Which compilers do you find are slower?
>
> Not necessarily slower, but Sun CC is about the same speed. And
> the version of it that I'm using (5.5) doesn't support
> everything in templates -- I don't think it supports two phased
> lookup.
>
> Back when g++ didn't support two phased lookup, it was a lot,
> lot faster than Sun CC.

Sun CC must be really bad then, because I've been using gcc 3.2 (no two
phase lookup), both on Windows and Linux, and find it very lethargic.

> compile time. My impression, compared with other compilers, is
> that it actually does a surprisingly good job, both in terms of
> compile speeds and optimization.

I'm getting the feeling that you're only comparing it to Sun CC... or
do you have other compilers in mind?

>
> > And on a side note, I think it's telling how few responses
> > there have been to this thread. Relating some practical
> > experiences would IMO yield a lot more progress than endless
> > opining on the theoretical aspects of GC.
>
> That's probably because the question was an obvious troll.
> There's so much literature available on the network that it
> seems obvious that anyone who isn't aware of major projects
> using GC doesn't want to be aware. The "my mind's made up,
> don't confuse me with the facts" syndrome.
>

That's an interesting way of dismissing the OP's honestly asked
question.

You're saying that non-deterministic finalization in C++ is so
prevalent, that it's silly to even ask around for experience of it.

Which GC systems are so prevalent then, in your experience? C++/CLI,
which just came out? The Boehm collector, which lists 20 or so projects
using it? Other homegrown/proprietary GC schemes?

Could you list some of the major projects you're referring to? Do they
compare favorably with similar projects using standard-fare C++ memory
management (auto_ptr/shared_ptr) ?

Jarl.

Pavel Vozenilek

unread,
Mar 30, 2006, 9:31:56 AM3/30/06
to

"kanze" wrote:

>> And on a side note, I think it's telling how few responses
>> there have been to this thread. Relating some practical
>> experiences would IMO yield a lot more progress than endless
>> opining on the theoretical aspects of GC.
>
> That's probably because the question was an obvious troll.
> There's so much literature available on the network that it
> seems obvious that anyone who isn't aware of major projects
> using GC doesn't want to be aware. The "my mind's made up,
> don't confuse me with the facts" syndrome.
>

I am not aware about large projects (gcc being exception).

I saw claims of high productivity attributed to GC
(30% is quite popular number for C++ or C family languages).

Such tool is highly interesting for me but I am
no experimenter and need to know results of
the others before even thinking about it.


The information I look for are not just performance
or productivity numbers but GC aware libraries,
and debugging techniques.

/Pavel

kanze

unread,
Mar 30, 2006, 9:33:58 AM3/30/06
to
Mirek Fidler wrote:
> Nemanja Trifunovic wrote:

[Concerning the performance of garbage collection...]


> I believe that it has something to do with allocation pattern
> and total amount of data app has to handle.

I'd say that it is self evident that the performance of any
memory management scheme will depend greatly on the allocation
patterns. In the past (say up until 10 years ago), it was more
or less standard practice to have several different
implementations of malloc on hand, and to switch between them if
performance seemed to be a problem -- the one that was fastest
for some applications was significantly slower for others.

In a similar manner, there are definitly applications where
garbage collection may not perform well. Or at least, certain
implementations of garbage collection -- like malloc back then,
there are different implementations which are optimal for
different patterns of use. It's also possible to tune most
applications -- with the Boehm collector, for example, if you
have large objects with no pointers (e.g. arrays of double), you
can allocate it with a different function, and the collector
won't scan the memory for pointers.

> If application creates a lot of temporary objects, but has a
> little of "permanent" data, garbage collection can be a win. I
> think many of those benchmarks fail to this categhory.

A lot of applications, too.

There's something called generational garbage collection. I've
not used it, so I cannot speak from actual experience, but the
idea is that objects tend to collect in two different
categories, semi-permanent, and very volatile. When an object
lives through two or more garbage collection cycles, it gets
moved into the semi-permanent category, and less attempts are
made to collect it. It sounds like something that would fit
well with my applications. (In fact, in my applications, very
few of the "semi-permanent" objects contain pointers, so
there is an obvious solution to speed things up with the Boehm
collector. To date, it's not been necessary.)

> If your dataset grows significantly, GC will have to spend
> more and more time in mark phase and performance will
> inevitable go down.

It depends, but it's true that garbage collection -- at least
the most wide spread versions -- works best when the lifetime of
objects is short. Roughly speaking, the time used in typical
implementations of garbage collection depends on the size of the
set of active objects when the collector runs; with typical
implementations of malloc, it depends on the number of mallocs
and frees. If your application allocates few, very big objects,
and keeps them around for long periods of time, garbage
collection will probably be less effective. From a performance
point of view -- it will still reduce the amount of work you
have to do.

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

kanze

unread,
Mar 30, 2006, 10:00:17 AM3/30/06
to
Nemanja Trifunovic wrote:
> kanze wrote:

>> (Another reason the C++ compiler might be slow is that it
>> implements full two-phase look-up. I've noticed a lot of
>> C++ compilers slowing down as they introduce full support
>> for templates.)

> If I remember correctly, two-phase name lookup was introduced
> with GCC 3.4. It was definitely slow in earlier versions.

I'm not sure what version it was introduced in, but I do know
that g++ 2.95.2 was about the fastest compiler around, back
then.

> Back to the point - I am sure that reasons other than GC can
> be found, but still have to see a "GC" application that
> performes well compared to similar "non-GC" ones.

Generally, people don't write two versions of the same thing,
just to see which is faster. I did read once about someone
having compiled X with malloc/free redefined to use GB_malloc
and do nothing, with the resulting code running faster, but I'm
not sure of any of the details. (That was a long time ago.) If
I recall right, after a couple of days of running, the
difference suddenly became very significant -- it seems that the
standard release of X at that time contained some memory leaks,
which meant that after a couple days (or weeks, I don't
remember) it started thrashing.

The rare benchmarks I've seen all show garbage collection as
being faster than manual memory management, but as I've pointed
out in another thread, I'm sceptical about how much information
you can really gather from a benchmark that you haven't
faked^H^H^H^H^Hwritten yourself.

Other than that, of course, a lot of non-C++ applications are
written which use garbage collection, and it doesn't seem to
slow them up. Why should it have a different effect in C++?

Let's face it, garbage collection is mainstream technology
today, and it wouldn't be if it couldn't provide the
performance. (Note that this has not always been the case, and
I find it quite understandable that Stroustrup considered it,
and decided against it on performance reasons, and perhaps other
reasons as well, in primitive C++. Given the evolution of the
technology, I would not be at all surprised if he favored adding
it to C++ today.)

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

kanze

unread,
Mar 30, 2006, 10:01:17 AM3/30/06
to
Mirek Fidler wrote:
>> You do have to compare things which are comparable. A
>> portable compiler will never be as fast as one designed for
>> a single platform (nor will it optimize as well).

> Well, while this sounds very "wise", in reality I do not see
> any practical reason why well designed C++ compiler should be
> slow because it is "portable".

Actually, the reason most well designed C++ compilers are slow
is because of conformance:-). G++ 2.95.2 was one of the fastest
compilers around, but that was without two phased lookup and a
lot of other things.

But genericity has a price, and the g++ back-end is extremely
generic. Every "portable" compiler I've worked on has had
performance problems. G++ is the exception (but I've not worked
on it, only with it.)

Also, even today, g++ does compare favorably with the two other
compilers I hae access to: VC++ and Sun CC. The Windows version
that I'm using is somewhat slower that VC++, probably because of
the CygWin layering, but the Linux version is significantly
faster. (In neither case, however, is the difference anything
to get excited about. Nothing like the slowdowns I experienced
with both Sun CC and g++ when upgrading to "conformant"
compilers.)

>> There's so much literature available on the network that it
>> seems obvious that anyone who isn't aware of major projects
>> using GC doesn't want to be aware. The "my mind's made up,
>> don't confuse me with the facts" syndrome.

> Actually, maybe original poster just wanted to be pointed in
> the right direction.

> Google "major C++ projects using garbage collection" does not
> yield anything useful in the first 50 hits.

Well, the Boehm collector has been discussed here more than
once. The obvious solution, if you want to know about garbage
collection, is to download it, install it, and find out for
yourself.

FWIW: I did so, and I wouldn't consider starting a new project
without it, unless I had to. (When third party libraries start
threads, it is sometimes difficult to find a configuration which
will work. If you have the sources to everything you want to
link in, however, getting it up and running in a simple
configuration takes about ten minutes, and afterwards, you can
almost forget about it.)

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

Nemanja Trifunovic

unread,
Mar 30, 2006, 1:53:58 PM3/30/06
to
> I'm not sure what version it was introduced in, but I do know
> that g++ 2.95.2 was about the fastest compiler around, back
> then.

No, it wasn't. At least Microsoft and Borland compilers were
significantly faster, and I bet most of other compilers as well but
since I haven't worked with them I'll restrict my claim only to MS and
Borland..

> Other than that, of course, a lot of non-C++ applications are
> written which use garbage collection, and it doesn't seem to
> slow them up. Why should it have a different effect in C++?

How do you now that? There is practicaly no way to write a non-GC Java
or C# application and compare it with a "regular" GC one.

Having worked a lot with GC languages (Java, C# and a very little
OCaml) I can claim that they generally *are* slower than non-GC
languages I worked with, no matter what benchamarks say.

Peter Dimov

unread,
Mar 30, 2006, 1:53:03 PM3/30/06
to
kanze wrote:

> The rare benchmarks I've seen all show garbage collection as
> being faster than manual memory management, but as I've pointed
> out in another thread, I'm sceptical about how much information
> you can really gather from a benchmark that you haven't
> faked^H^H^H^H^Hwritten yourself.

Garbage collection is definitely faster than manual memory management
when the collector never runs. It can also be faster, on average, when
the collector does run. But "on average" doesn't tell the whole story.
"Stop the world" pauses can be a problem if, for example, you have to
consistently deliver 25 frames per second, or you have a thread that
must not be stopped.

I know that there exist garbage collectors that don't stop the world,
but I haven't seen one for C++.

Mirek Fidler

unread,
Mar 30, 2006, 7:19:31 PM3/30/06
to
> Let's face it, garbage collection is mainstream technology
> today, and it wouldn't be if it couldn't provide the
> performance.

Well, I think if you insist on using mainstream technology, why you just
do not start using mainstream language?

If I ever decided to use GC, I would definitely rather used language
that is designed for GC, most likely C#.

However, I like C++ because I believe, despite mainstream technology
trends, that is provides higher productivity without the need for GC,
which (I believe!) also results in better performing code. And C++ is
the only available language which provides alternative to GC (destructors).

Mirek

Mirek Fidler

unread,
Mar 30, 2006, 7:17:51 PM3/30/06
to
> There's something called generational garbage collection. I've

Of course. But inevitably, even with generational garbage collection,
there must (or should) be times when complete mark phase has to happen.

I do not like idea of my code freezing for a moment at random time...

> It depends, but it's true that garbage collection -- at least
> the most wide spread versions -- works best when the lifetime of
> objects is short. Roughly speaking, the time used in typical
> implementations of garbage collection depends on the size of the
> set of active objects when the collector runs; with typical
> implementations of malloc, it depends on the number of mallocs
> and frees. If your application allocates few, very big objects,
> and keeps them around for long periods of time, garbage
> collection will probably be less effective.

Nope. That might be true for conservative GC. Otherwise, big objects
usually do not contain too many pointers to scan through and they are
usually easily comparable as targets for marking.

I believe that worst case scenario for modern GC is in fact a very large
number of very _small_ objects allocated for long periods of time.

Mirek

Mirek Fidler

unread,
Mar 30, 2006, 7:25:28 PM3/30/06
to

>>Well, while this sounds very "wise", in reality I do not see
>>any practical reason why well designed C++ compiler should be
>>slow because it is "portable".
>
>
> Actually, the reason most well designed C++ compilers are slow
> is because of conformance:-). G++ 2.95.2 was one of the fastest
> compilers around, but that was without two phased lookup and a
> lot of other things.

Nope, if I remember well, it was as slow as the latest version.

> Also, even today, g++ does compare favorably with the two other
> compilers I hae access to: VC++ and Sun CC. The Windows version
> that I'm using is somewhat slower that VC++, probably because of

2-4 times slower than VC++ 7.1 depending on situation. That is quite bit
more than "somewhat".

> the CygWin layering, but the Linux version is significantly
> faster.

Well, it is a bit faster when compiled for AMD64, but nothing that would
completely change the situation.

Mirek

Nemanja Trifunovic

unread,
Mar 30, 2006, 7:23:45 PM3/30/06
to

kanze wrote:
> Also, even today, g++ does compare favorably with the two other
> compilers I hae access to: VC++ and Sun CC. The Windows version
> that I'm using is somewhat slower that VC++, probably because of
> the CygWin layering, but the Linux version is significantly
> faster. (In neither case, however, is the difference anything
> to get excited about. Nothing like the slowdowns I experienced
> with both Sun CC and g++ when upgrading to "conformant"
> compilers.)


You must be kidding. g++ is slower than any version of VC++ I've ever
worked with (even VC2005 which has ridiculous link time). And I have
used different versions of g++ on different platforms (Linux 2.2, 2.4,
2.6, FreeBSD 4.8, 6.0, Windows (MinGW)) and it was *always* slower than
VC++, and by a large margin. Compiling even "hello world" with g++
makes me nervous, and for real projects it is hardly bearable, even
with tools like ccache.

SunCC I have never tried, so I will refrain from commenting.

Andrei Alexandrescu (See Website For Email)

unread,
Mar 30, 2006, 11:59:28 PM3/30/06
to
Mirek Fidler wrote:
> However, I like C++ because I believe, despite mainstream technology
> trends, that is provides higher productivity without the need for GC,
> which (I believe!) also results in better performing code. And C++ is
> the only available language which provides alternative to GC
> (destructors).

We're going in circles. :o) This entire thread was designed to reconcile
two productivity-increasing technologies: destructors and GC. Making the
two work together smoothly would ideally combine the advantages of both,
and mollify the disadvantages of either.

Andrei

Mirek Fidler

unread,
Mar 31, 2006, 3:05:06 AM3/31/06
to
Andrei Alexandrescu (See Website For Email) wrote:
> Mirek Fidler wrote:
>
>>However, I like C++ because I believe, despite mainstream technology
>>trends, that is provides higher productivity without the need for GC,
>>which (I believe!) also results in better performing code. And C++ is
>>the only available language which provides alternative to GC
>>(destructors).
>
>
> We're going in circles. :o) This entire thread was designed to reconcile
> two productivity-increasing technologies: destructors and GC. Making the
> two work together smoothly would ideally combine the advantages of both,
> and mollify the disadvantages of either.

The problem is that "work together smoothly" is most likely impossible.
Best we can get (that, if I understand things well, covers both your
proposal and C++/CLI) is creating two categhories of classes - GC
collected and destructed ("deterministic"). That would effectively break
the language to two sublanguages.

Besides, your proposal is so much complicated that it can hardly be
described as "smooth".

Mirek

Sergey P. Derevyago

unread,
Mar 31, 2006, 8:08:55 AM3/31/06
to
Peter Dimov wrote:
> I know that there exist garbage collectors that don't stop the world,
>
Once again: explain please how this could be possible in the case of
regular
C++ program. Don't you have to examine the registers, the stacks and
so on?

> but I haven't seen one for C++.
>

Sure, it's impossible.
--
With all respect, Sergey. http://ders.angen.net/
mailto : ders at skeptik.net

kanze

unread,
Mar 31, 2006, 10:05:54 AM3/31/06
to
Mirek Fidler wrote:
> > There's something called generational garbage collection. I've

> Of course. But inevitably, even with generational garbage
> collection, there must (or should) be times when complete mark
> phase has to happen.

> I do not like idea of my code freezing for a moment at random
> time...

You mean like when the last smart pointer to a chain of objects
is dropped. Whether you like it or not, practically speaking,
as soon as the destructor of one object can trigger destruction
of another object, you've got it. The only way to avoid it is
to avoid non-trivial destructors, and that's a price I'm not
willing to pay.

There are real time garbage collectors with guaranteed latency,
if that's what you need. It is also possible to force garbage
collection at moments when it is least detrimental to your
program.

> > It depends, but it's true that garbage collection -- at
> > least the most wide spread versions -- works best when the
> > lifetime of objects is short. Roughly speaking, the time
> > used in typical implementations of garbage collection
> > depends on the size of the set of active objects when the
> > collector runs; with typical implementations of malloc, it
> > depends on the number of mallocs and frees. If your
> > application allocates few, very big objects, and keeps them
> > around for long periods of time, garbage collection will
> > probably be less effective.

> Nope. That might be true for conservative GC.

True. I was thinking of C++, and practically speaking, I don't
see many possibilities for a relocating collector. Regretfully,
but that's the way it is.

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

kanze

unread,
Mar 31, 2006, 10:03:15 AM3/31/06
to
Nemanja Trifunovic wrote:
> kanze wrote:
> > Also, even today, g++ does compare favorably with the two
> > other compilers I hae access to: VC++ and Sun CC. The
> > Windows version that I'm using is somewhat slower that VC++,
> > probably because of the CygWin layering, but the Linux
> > version is significantly faster. (In neither case, however,
> > is the difference anything to get excited about. Nothing
> > like the slowdowns I experienced with both Sun CC and g++
> > when upgrading to "conformant" compilers.)

>
> You must be kidding. g++ is slower than any version of VC++
> I've ever worked with (even VC2005 which has ridiculous link
> time).

I just measured it. Under Windows, g++ 3.3.3 (cygwin special)
is a little less than 20% slower than VC++ 2005, for exactly the
same build (making both debug and optimized versions of a number
of libraries, plus the unit tests). The same build with g++
under Linux is about 30% faster than VC++ under windows.

> And I have used different versions of g++ on different
> platforms (Linux 2.2, 2.4, 2.6, FreeBSD 4.8, 6.0, Windows
> (MinGW)) and it was *always* slower than VC++, and by a large
> margin.

Well, g++ 3.3.3 isn't significantly slower than VC++ 2005 under
Windows.

Maybe you're doing something different in the two cases -- using
pre-compiled headers under VC++, for example.

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

kanze

unread,
Mar 31, 2006, 10:02:03 AM3/31/06
to
Mirek Fidler wrote:
> >>Well, while this sounds very "wise", in reality I do not see
> >>any practical reason why well designed C++ compiler should
> >>be slow because it is "portable".

> > Actually, the reason most well designed C++ compilers are
> > slow is because of conformance:-). G++ 2.95.2 was one of
> > the fastest compilers around, but that was without two
> > phased lookup and a lot of other things.

> Nope, if I remember well, it was as slow as the latest version.

My build times increased by a factor of three when I upgraded.

> > Also, even today, g++ does compare favorably with the two
> > other compilers I hae access to: VC++ and Sun CC. The
> > Windows version that I'm using is somewhat slower that VC++,
> > probably because of

> 2-4 times slower than VC++ 7.1 depending on situation. That is
> quite bit more than "somewhat".

It's also a difference that I can't reproduce on my machine.
G++ 3.3.3 (cygwin special), vs. the 2005 free download of VC++
(version 14.00.50727.42 is what the compiler says).

> > the CygWin layering, but the Linux version is significantly
> > faster.

> Well, it is a bit faster when compiled for AMD64, but nothing
> that would completely change the situation.

The Linux machine here is not an AMD. It's also not the same
machine as the Windows machine. But when I run my benchmarks,
performance is within 10%-15% on the two machines -- only g++
shows any significant difference.

I find it curious that this "performance" problem with g++ only
appeared when it was mentionned that g++ uses garbage
collection. Before this week, I'd always heard the reverse.
And I know that in my own developments (which always compile
with at least two different compilers), g++ has never been
noticeably slower, and in many cases (e.g. g++ 2.95.2 vs. Sun CC
5.1), it was decidedly faster.

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

kanze

unread,
Mar 31, 2006, 10:04:50 AM3/31/06
to
Peter Dimov wrote:
> kanze wrote:

> > The rare benchmarks I've seen all show garbage collection as
> > being faster than manual memory management, but as I've pointed
> > out in another thread, I'm sceptical about how much information
> > you can really gather from a benchmark that you haven't
> > faked^H^H^H^H^Hwritten yourself.

> Garbage collection is definitely faster than manual memory
> management when the collector never runs.

Which, of course, isn't difficult to arrange for if you're
writing a benchmark:-). It wouldn't surprise me if this is the
case in some of the benchmarks. For others, I don't think so.

(Interestingly, I would imagine that the g++ compiler would be
one of these cases where in fact, garbage collection never
runs.)

> It can also be faster, on average, when the collector does
> run.

Depending on how it is used, in some applications, it can also
do most of its work when the rest of the application is idle.

> But "on average" doesn't tell the whole story. "Stop the
> world" pauses can be a problem if, for example, you have to
> consistently deliver 25 frames per second, or you have a
> thread that must not be stopped.

For that particular example, there is a simple solution -- force
it to run after each frame is delivered. It will run in the
optimal conditions (very little memory allocated to scan, etc.),
and because it is being run often, therer will be less memory
for it to collect.

There are doubtlessly other cases, however, where this effect is
a problem, and there is no simple solution. Not every program
benefits from garbage collection. But enough do to make it an
option worth having.

> I know that there exist garbage collectors that don't stop the
> world, but I haven't seen one for C++.

I think that you can configure the Boehm collector to be
partially incremental, but I'm not sure. The pauses haven't
been a problem in my applications (although they probably would
be if I had to deliver something every 40 milliseconds).

There's no free lunch. The collector I use does cause the
programs to use more memory. It's not a problem in my
applications, but it could be for some. Other collectors don't
have this problem, but do run slower. From what I understand,
real-time collectors, which provide guaranteed latency, have a
higher average time used. In this respect, they are exactly
like malloc -- Sun CC still comes with three different
implementations of malloc, so you can choose the one best for
your application. (Supposing that you have a performance
problem, and the profiler shows that memory allocation is part
of it.)

In the end, the philosophy of C++ has been to provide the most
flexibility possible to the programmers, and the let each
programmer choose what he wants or needs. There are doubtlessly
C++ programmers today who, for one reason or another, don't use
exceptions -- I doubt that I'd use them in a device driver, at
least not in the interupt handling routines. Others don't want
or need inheritance, or templates (that one's hard to believe),
or whatever. But they're there for us to choose, if and when we
feel them appropriate. And because they are standard, we can
feel fairly sure that choosing to use them, when appropriate,
will not cause problems with third party libraries.

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

kanze

unread,
Mar 31, 2006, 10:04:28 AM3/31/06
to
Nemanja Trifunovic wrote:
> > I'm not sure what version it was introduced in, but I do
> > know that g++ 2.95.2 was about the fastest compiler around,
> > back then.

> No, it wasn't. At least Microsoft and Borland compilers were
> significantly faster, and I bet most of other compilers as
> well but since I haven't worked with them I'll restrict my
> claim only to MS and Borland..

My experience was that g++ 2.95.2 and VC++ 6.0 were about the
same, with perhaps a slight edge for g++. But I can't reproduce
than now, as I no longer have access to either of these
dinosaurs.

> > Other than that, of course, a lot of non-C++ applications
> > are written which use garbage collection, and it doesn't
> > seem to slow them up. Why should it have a different effect
> > in C++?

> How do you now that?

>From experience. I use applications written in other languages
as well.

> There is practicaly no way to write a non-GC Java or C#
> application and compare it with a "regular" GC one.

> Having worked a lot with GC languages (Java, C# and a very
> little OCaml) I can claim that they generally *are* slower
> than non-GC languages I worked with, no matter what
> benchamarks say.

You claim... no matter what [measurements show]...

I see. I don't put too much value in the benchmarks myself; I
know that I could write one to prove which ever side was paying
me. But still, the absense of benchmarks in which C++ is faster
than Java is somewhat telling. And my own experience with Java
suggests that the PC implementations are at least as fast as
C++, if not faster -- on other platforms, the optimization
technology doesn't seem to be applied as rapidly.

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

kanze

unread,
Mar 31, 2006, 10:05:22 AM3/31/06
to
Andrei Alexandrescu (See Website For Email) wrote:
> Mirek Fidler wrote:
> > However, I like C++ because I believe, despite mainstream
> > technology trends, that is provides higher productivity
> > without the need for GC, which (I believe!) also results in
> > better performing code. And C++ is the only available
> > language which provides alternative to GC (destructors).

> We're going in circles. :o) This entire thread was designed to
> reconcile two productivity-increasing technologies:
> destructors and GC. Making the two work together smoothly
> would ideally combine the advantages of both, and mollify the
> disadvantages of either.

You're confusing threads, Andrei. This isn't the one you
started. This one started by someone posting (rephrased) a
demand concerning information about existing use of garbage
collection, such as the Boehm collector, and then more or less
stating that:

-- if there is no such use, then we lack existing practice, so
you can't have it,

-- if there is, and it is difficult, then we have proof that it
doesn't work well, so you can't have it, and

-- if there is, and it works well, then the status quo is fine,
so you can't have it.

In the meantime, I've learned that g++ is horribly slow: never
heard that one before, and it doesn't correspond to my
experience, but since someone posted that it uses garbage
collection, it must be.

As you say, we're going around in circles. For what it's worth,
I'm using the Boehm collector today, and I've had absolutly no
problem with destructors because of it. I suppose that some
will say that this is because I'm incompetent, and don't realize
a problem when I encouter it (or that I'm just too lazy to do it
right), but the programs are working, without resource leaks.

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

Peter Dimov

unread,
Mar 31, 2006, 10:43:07 AM3/31/06
to
Sergey P. Derevyago wrote:
> Peter Dimov wrote:
> > I know that there exist garbage collectors that don't stop the world,
> >
> Once again: explain please how this could be possible in the case of
> regular C++ program. Don't you have to examine the registers, the stacks
> and so on?

I have no idea. :-)

http://citeseer.ist.psu.edu/255424.html

Non-Compacting Memory Allocation and Real-Time Garbage Collection
(1996)
Mark S. Johnstone

seems a good paper on the subject, but I haven't read it yet.

jlin...@hotmail.com

unread,
Apr 1, 2006, 8:44:54 PM4/1/06
to
kanze wrote:

>>
>> You're confusing threads, Andrei. This isn't the one you
>> started. This one started by someone posting (rephrased) a
>> demand concerning information about existing use of garbage
>> collection, such as the Boehm collector, and then more or less
>> stating that:


I believe it was a request :)

>>
>> -- if there is no such use, then we lack existing practice, so
>> you can't have it,
>>
>> -- if there is, and it is difficult, then we have proof that it
>> doesn't work well, so you can't have it, and
>>
>> -- if there is, and it works well, then the status quo is fine,
>> so you can't have it.
>>


Rereading the thread, I can't find a basis for any of those statements.
Maybe you can help me out.

There are a lot of us who don't have the time or resources to get
involved in productive experimentation and research, especially on the
scale that would be required to form an informed opinion of how well
C++ with GC works in practice, on real-world projects. The next best
thing is to have a look at the findings of others who _are_ in a better
position to evaluate such technologies.

We've been inundated with 900+ posts in two other threads on this
subject, with very little mention of large-scale practical experience
of, let us say, the Boehm collector.

Hence the OP's question, which you summarily dismissed as a troll.

Could you list a few of the major projects you know about, that are
using C++ and GC? You've mentioned that there are a lot of them. It
would help the discussion a lot more than making sweeping
generalizations about other posters.


>> In the meantime, I've learned that g++ is horribly slow: never
>> heard that one before, and it doesn't correspond to my
>> experience, but since someone posted that it uses garbage
>> collection, it must be.


As was pointed out several times in this thread, g++ isn't even written
in C++, so its relevance to the discussion on C++/GC is tenuous at
best. Whether or not g++ can be considered slow is a different matter.
By your own admission its 20% slower than VC++, although I guess you
ascribe that to the cygwin layering.

Here are the build times for a project I'm working on. A build involves
building Boost.Serialization, Boost.Threads, the project itself, and
the test. A complete release build, using Boost.Build (bjam), with
exact same parameters but differing compilers yields these numbers:

Visual C++ 7.1: 1m 40s
Visual C++ 8.0: 2m 00s
CodeWarrior 9.2: 2m 20s
mingw(gcc 3.2): 8m 00s

FWIW, here are the resulting executable sizes:

Visual C++ 7.1: 620 kb
Visual C++ 8.0: 724 kb
CodeWarrior 9.2: 904 kb
mingw(gcc 3.2): 2500 kb

Just a benchmark, as you say. YMMV. One of those compilers really does
come out looking a lot worse than the others though. If you don't
believe me, you can download the source
(http://www.codeproject.com/threads/Rcf_Ipc_For_Cpp.asp), and build
test/Test_Minimal.cpp yourself.

And if you know some way of improving gcc's performance, I'd be very
happy to hear about it.

Regards,
Jarl.

Mirek Fidler

unread,
Apr 1, 2006, 8:54:35 PM4/1/06
to
>>>>I do not like idea of my code freezing for a moment at random
>>>>time...
>
>>
>>
>> You mean like when the last smart pointer to a chain of objects
>> is dropped.


Using reference counting smart pointers is just another bad idea...

> Whether you like it or not, practically speaking,

>> as soon as the destructor of one object can trigger destruction
>> of another object, you've got it.


That is true, however places where this happens are predictable, that
can make the difference. Moreover, there will be still much less
operational complexity with even large destructor v.s. mark/sweep phase.


>>>>Nope. That might be true for conservative GC.
>
>>
>>
>> True. I was thinking of C++, and practically speaking, I don't
>> see many possibilities for a relocating collector. Regretfully,
>> but that's the way it is.


Does not need to be relocating, just have enough type info to know about
positions of pointers (if that is possible for PODs is another question...)

BTW, thinking about that again, if conservative GC exists and works,
what is the advantage of pushing it to the language standard? Why not
just use it? Conservative GC for C++ could simply be defined a an
additional standard - it is defacto standard now anyway... (and we all
know that defacto standards tend to be pretty strong in computing
industry...)

Mirek

Mirek Fidler

unread,
Apr 1, 2006, 8:59:25 PM4/1/06
to
>>>>2-4 times slower than VC++ 7.1 depending on situation. That is
>>>>quite bit more than "somewhat".
>
>>
>>
>> It's also a difference that I can't reproduce on my machine.
>> G++ 3.3.3 (cygwin special), vs. the 2005 free download of VC++
>> (version 14.00.50727.42 is what the compiler says).


Strange indeed. It is true that 2005 is slower a bit, as MS decided to
remove automatic precompiled headers. Must have something do to with
structure of your code, e.g. including <windows.h> (or <X11/Xlib.h>,
<X11/Xutil.h>, <X11/Xatom.h>, <X11/Xft/Xft.h>) can make all the difference.


>>>>Well, it is a bit faster when compiled for AMD64, but nothing
>>>>that would completely change the situation.
>
>>
>>
>> The Linux machine here is not an AMD. It's also not the same
>> machine as the Windows machine. But when I run my benchmarks,
>> performance is within 10%-15% on the two machines -- only g++
>> shows any significant difference.


Oh, perhaps we are speaking about different things here... I am speaking
about speed of compilation, not the speed of compilation product (10-15%
is quite reasonable estimate there).


>> I find it curious that this "performance" problem with g++ only
>> appeared when it was mentionned that g++ uses garbage
>> collection.


In fact, I do not believe that it has much to do with GC.

Mirek

David Abrahams

unread,
Apr 1, 2006, 9:08:09 PM4/1/06
to
"kanze" <ka...@gabi-soft.fr> writes:


>> I find it curious that this "performance" problem with g++ only
>> appeared when it was mentionned that g++ uses garbage
>> collection. Before this week, I'd always heard the reverse.


Not if you read http://www.boost-consulting.com/mplbook. Appendix C
contains the graphs showing how much slower g++ is at template
instantiation than VC++.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Peter Dimov

unread,
Apr 1, 2006, 9:02:29 PM4/1/06
to
kanze wrote:
> Mirek Fidler wrote:
> > > There's something called generational garbage collection. I've
>
> > Of course. But inevitably, even with generational garbage
> > collection, there must (or should) be times when complete mark
> > phase has to happen.
>
> > I do not like idea of my code freezing for a moment at random
> > time...
>
> You mean like when the last smart pointer to a chain of objects
> is dropped. Whether you like it or not, practically speaking,
> as soon as the destructor of one object can trigger destruction
> of another object, you've got it. The only way to avoid it is
> to avoid non-trivial destructors, and that's a price I'm not
> willing to pay.

This can be a problem in real time applications, but:

- it only stalls the current thread;
- it's relatively easy to avoid. Just move the pointer to a 'destroy
queue' instead and clear the queue at appropriate times.

> There are real time garbage collectors with guaranteed latency,
> if that's what you need.

It is my current understanding that all known real time collectors
require compiler support. They need extra code on every pointer load,
every pointer store, or both. In practice this means smart pointers,
atomic operations and memory synchronization, placing realtime GC
somewhere between stop the world tracing GC and reference counting. But
if you have a link to a paper that proves otherwise I'll be glad to
bring my GC "knowledge" up to date. :-)

Andrei Alexandrescu (See Website For Email)

unread,
Apr 1, 2006, 9:04:45 PM4/1/06
to
Mirek Fidler wrote:

>> Andrei Alexandrescu (See Website For Email) wrote:
>>
>
>>>>Mirek Fidler wrote:
>>>>
>>>>
>>
>>>>>>However, I like C++ because I believe, despite mainstream technology
>>>>>>trends, that is provides higher productivity without the need for GC,
>>>>>>which (I believe!) also results in better performing code. And C++ is
>>>>>>the only available language which provides alternative to GC
>>>>>>(destructors).
>>
>>>>
>>>>
>>>>We're going in circles. :o) This entire thread was designed to
reconcile
>>>>two productivity-increasing technologies: destructors and GC.
Making the
>>>>two work together smoothly would ideally combine the advantages of
both,
>>>>and mollify the disadvantages of either.
>
>>
>>
>> The problem is that "work together smoothly" is most likely impossible.
>> Best we can get (that, if I understand things well, covers both your
>> proposal and C++/CLI) is creating two categhories of classes - GC
>> collected and destructed ("deterministic"). That would effectively break
>> the language to two sublanguages.


The language changes I discuss bring no change in usage syntax, which I
believe is important. The only change in syntax is in the declaration of
the class. Other than that, the compiler takes care of the semantic
differences between deterministic and collected classes. I think this is
a compelling property, and that it's unfair to say that it breaks C++
into two sublanguages. Semantically, yes, but syntactically, very very
little.


>> Besides, your proposal is so much complicated that it can hardly be
>> described as "smooth".


While I'd agree some could see it as "not smooth", it's not complicated;
it's the nature of newsgroup discussion that makes it look much more
complicated than it really is. At the end of the day, all I bring is:

- You can choose at declaration time whether a type is deterministic or
collected;

- For deterministic types pointers effectively behave like smart
pointers, with unchanged syntax;

- The points-to relationships between collected and non-collected
objects are restricted statically.

That's the gist of it.


Andrei

Jeremy Jurksztowicz

unread,
Apr 1, 2006, 9:15:40 PM4/1/06
to
>> You mean like when the last smart pointer to a chain of objects
>> is dropped. Whether you like it or not, practically speaking,
>> as soon as the destructor of one object can trigger destruction
>> of another object, you've got it. The only way to avoid it is
>> to avoid non-trivial destructors, and that's a price I'm not
>> willing to pay.

Or install a smart pointer destroyer which sends the object to another
context for destruction. There are many more ways in which object
destruction can be coerced to behave in a particular way. This, in my
opinion, is why destructors are preferable to GC, when timing matters.

PS : I tuned in to this thread in the hope of the OP's question getting
an answer. Isn't it odd that so few relevant links are posted? For
those of us who are CASUALLY interested in GC in C++ programs, this
sends a negative message, AS IF the technology and techniques needed to
manage it are immature. I do not have time for scouring the internet,
collating and analyzing (likely very complex) data myself.

Sincerely,
Jeremy Jurksztowicz

Wu Yongwei

unread,
Apr 1, 2006, 9:12:24 PM4/1/06
to
jlin...@hotmail.com wrote:

> kanze wrote:
>
> > It's not the slowest, either. And I think you'll find that most
> > of the speed penalty it takes is due to its being generic.
> > Supporting multiple languages for multiple platforms isn't free.


> > (Another reason the C++ compiler might be slow is that it
> > implements full two-phase look-up. I've noticed a lot of C++
> > compilers slowing down as they introduce full support for
> > templates.)
> >

> > --
>
> Which compilers do you find are slower? On Windows I've used a number
> (Intel, Metrowerks, Microsoft, Borland) and gcc really is exceptionally
> slow... And on top of that the executables it produces are
> substantially less optimized. It's hardly a poster boy for garbage
> collection.

I have tried several compilers on Windows, and GCC is really the
slowest (in building). However, I cannot say it optimizes badly. My
experience shows it optimizes better than Digital Mars and Borland.

To answer some questions in other posts, some facts are here:

1) The speed of GCC 2.95 is acceptable on Windows
2) Relatively GCC 3.2-3.3 is much slower
3) GCC 3.4 (with the introduction of two-phase look-up, according to
other posts) is even slower
4) On the same machine running Linux and Windows, the same version of
GCC runs MUCH faster on Linux, and generates better-optimized code
compared to earlier versions, which is not necessarily the case on
Windows. So I guess most people using GCC are on Linux, where it is
optimized well and has acceptable performance. There simply may not be
enough people working on the Windows version of GCC.

Best regards,

Yongwei

Herb Sutter

unread,
Apr 1, 2006, 9:13:04 PM4/1/06
to
Mirek Fidler <c...@volny.cz> wrote:
>Andrei Alexandrescu (See Website For Email) wrote:
>> We're going in circles. :o) This entire thread was designed to reconcile
>> two productivity-increasing technologies: destructors and GC. Making the
>> two work together smoothly would ideally combine the advantages of both,
>> and mollify the disadvantages of either.
>
>The problem is that "work together smoothly" is most likely impossible.
>Best we can get (that, if I understand things well, covers both your
>proposal and C++/CLI) is creating two categhories of classes - GC
>collected and destructed ("deterministic"). That would effectively break
>the language to two sublanguages.

FWIW, C++/CLI explicitly does _not_ create two categories of classes like
"GC" and "destructed." A key feature is uniformity -- today, any type
(including a CLI type) can have a destructor, and in the future it's
intended that any type (including a C++ type) can be allocated on the GC'd
CLI heap.

In my opinion, it would absolutely be wrong to conflate where/how
instances a type is allocated (e.g., gc vs. non-gc) with the kind of type
it is. This is a mistake that the Managed Extensions made, and that
C++/CLI corrected. C++/CLI does have new type categories, such as ref
class and value class, but this is because they are behaviorally different
(e.g., virtual function dispatch during construction/destruction), and not
because of where they can be allocated (and in the future it's intended
that any type be able to be allocated on any heap).

For more details on this and other topics, see A Design Rationale for
C++/CLI, http://www.gotw.ca/publications/C++CLIRationale.pdf .

Herb

---
Herb Sutter (www.gotw.ca) (www.pluralsight.com/blogs/hsutter)

Convener, ISO WG21 (C++ standards committee) (www.gotw.ca/iso)
Architect, Developer Division, Microsoft (www.gotw.ca/microsoft)

Wu Yongwei

unread,
Apr 1, 2006, 9:13:30 PM4/1/06
to
kanze wrote:

> Nemanja Trifunovic wrote:
> > kanze wrote:
> > > Also, even today, g++ does compare favorably with the two
> > > other compilers I hae access to: VC++ and Sun CC. The
> > > Windows version that I'm using is somewhat slower that VC++,
> > > probably because of the CygWin layering, but the Linux
> > > version is significantly faster. (In neither case, however,
> > > is the difference anything to get excited about. Nothing
> > > like the slowdowns I experienced with both Sun CC and g++
> > > when upgrading to "conformant" compilers.)
>
> >
> > You must be kidding. g++ is slower than any version of VC++
> > I've ever worked with (even VC2005 which has ridiculous link
> > time).
>
> I just measured it. Under Windows, g++ 3.3.3 (cygwin special)
> is a little less than 20% slower than VC++ 2005, for exactly the
> same build (making both debug and optimized versions of a number
> of libraries, plus the unit tests). The same build with g++
> under Linux is about 30% faster than VC++ under windows.

Just a guess, but I think your machine must have a big amount of memory
(512 MB or bigger). I believe GCC (esp. the new versions) eats a lot
more memory than VC++.

I did not know that GCC uses GC. However, this quite makes sense now.
Really, Java is not slow on big-memory machines. On a new server box,
the Java test code to calculate prime numbers is nearly as fast as the
identical C++ code! Of course it does not happen on my old laptop.

Best regards,

Yongwei

Andrei Alexandrescu (See Website For Email)

unread,
Apr 2, 2006, 4:44:55 AM4/2/06
to
Herb Sutter wrote:
> In my opinion, it would absolutely be wrong to conflate where/how
> instances a type is allocated (e.g., gc vs. non-gc) with the kind
> of type
> it is. This is a mistake that the Managed Extensions made, and that
> C++/CLI corrected.

That blows one of my tenets in the air. Could you please summarize what
the experience with the Managed Extensions has shown, that revealed it's
a mistake to conflate storage regime with the type?

And, how does C++/CLI achieve type safety in the presence of both
destructors and garbage collection? Something's gotta give; you could
either leak resources, have zombie objects, or risk dangling pointer
accesses. I couldn't find a better way than associating the regime with
the type, and I'd be interested on how C++/CLI addressed this issue.

My current understanding is that C++/CLI can leak resources no matter
how they are designed. If that's the case, I will surmise that my design
is better.


Andrei

Pavel Vozenilek

unread,
Apr 2, 2006, 2:09:25 PM4/2/06
to

"David Abrahams" wrote:

> "kanze" writes:
>
>>> I find it curious that this "performance" problem with g++ only
>>> appeared when it was mentionned that g++ uses garbage
>>> collection. Before this week, I'd always heard the reverse.
>
>
> Not if you read http://www.boost-consulting.com/mplbook. Appendix C
> contains the graphs showing how much slower g++ is at template
> instantiation than VC++.
>

Getting definitely off-topic: IME instantiation speed differs
a lot and presence or lack of GC may be minor factor.

Intel, for example, is very, very slow here and it doesn't use
GC, AFAIK. BCB is order of magnitude faster (module bugs).


A valid comparison would be having two version
of the same compiler, one GC enabled, one with
traditional allocator.

/Pavel

Sergey P. Derevyago

unread,
Apr 2, 2006, 2:08:25 PM4/2/06
to
Peter Dimov wrote:
> http://citeseer.ist.psu.edu/255424.html
>
> Non-Compacting Memory Allocation and Real-Time Garbage Collection
> (1996)
> Mark S. Johnstone
>
> seems a good paper on the subject, but I haven't read it yet.
>
It stops the world (at least).

In particular, 5.8.3. "Performing an increment of garbage
collection
work" section tells: ... the root set is traced _atomically_ and all
objects
pointed to by root variables are grayed.


--
With all respect, Sergey. http://ders.angen.net/
mailto : ders at skeptik.net

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Mirek Fidler

unread,
Apr 2, 2006, 2:12:30 PM4/2/06
to
> I have tried several compilers on Windows, and GCC is really the
> slowest (in building). However, I cannot say it optimizes badly. My
> experience shows it optimizes better than Digital Mars and Borland.
>
> To answer some questions in other posts, some facts are here:
>
> 1) The speed of GCC 2.95 is acceptable on Windows
> 2) Relatively GCC 3.2-3.3 is much slower
> 3) GCC 3.4 (with the introduction of two-phase look-up, according to
> other posts) is even slower
> 4) On the same machine running Linux and Windows, the same version of
> GCC runs MUCH faster on Linux, and generates better-optimized code
> compared to earlier versions, which is not necessarily the case on
> Windows. So I guess most people using GCC are on Linux, where it is
> optimized well and has acceptable performance. There simply may
> not be
> enough people working on the Windows version of GCC.

Slightly off-topic:

BTW, if there is something to worry about C++ in the long term, it is
compilers. After all those years, there is not a compiler that would
satisfy at least two points of 4 critical:

- be standard compliant
- be fast
- produce optimal code
- be free

Compare to Java or C# (yes, I know, they are much easier to compile).

Mirek

Mirek Fidler

unread,
Apr 2, 2006, 2:10:47 PM4/2/06
to
>> But "on average" doesn't tell the whole story. "Stop the
>> world" pauses can be a problem if, for example, you have to
>> consistently deliver 25 frames per second, or you have a
>> thread that must not be stopped.
>
>
> For that particular example, there is a simple solution -- force
> it to run after each frame is delivered. It will run in the

Nope. Modern games are 512MB+ beasts. Top raw memory bandwidth is
~5GB/s. There is no way how you could do 25 mark phases of 512MB per
second.

Mirek

Nemanja Trifunovic

unread,
Apr 3, 2006, 2:41:08 AM4/3/06
to

kanze wrote:
> I just measured it. Under Windows, g++ 3.3.3 (cygwin special)
> is a little less than 20% slower than VC++ 2005, for exactly the
> same build (making both debug and optimized versions of a number
> of libraries, plus the unit tests).

Under Windows, I use MinGW (minimalist GNU for Windows) which does not
have the overhead of cygwin, and the compile time was around three
times longer than with VC 7.1. With VC8 (aka 2005) the difference is
admittedly smaller, bu still visible.

> The same build with g++
> under Linux is about 30% faster than VC++ under windows.
>

For me, gcc Linux builds are faster than Windows ones only when I use
ccache. Otherwise, I can't notice any difference.

An obvious question: did you compare the build time on a same machine
(Windows and Linux dual boot)?f

Nemanja Trifunovic

unread,
Apr 3, 2006, 2:39:50 AM4/3/06
to

Wu Yongwei wrote:
> On a new server box,
> the Java test code to calculate prime numbers is nearly as fast as the
> identical C++ code! Of course it does not happen on my old laptop.


That's one of the biggest problems I have with benchmarks: most of them
compute prime numbers or fibonacci numbers or do something else that
has no relevance for the real-life applications speed.

Pavel Vozenilek

unread,
Apr 3, 2006, 3:23:54 AM4/3/06
to

"Mirek Fidler" wrote:

> BTW, if there is something to worry about C++ in the long term, it is
> compilers. After all those years, there is not a compiler that would
> satisfy at least two points of 4 critical:
>
> - be standard compliant
> - be fast
> - produce optimal code
> - be free
>

Digital Mars is [b], [d] (currently), I would say [c] is good.
Currently it doesn't handle Boost but AFAIK progress
is being made.

Borland C++ free compiler 5.5 is [b] and [d],
its output isn't that bad. Standard compatibility
is problem but at least STL can be handled.

Intel C++ for Linux is [d], probably [c],
probably [a] and almost surely not [b].

/Pavel

Herb Sutter

unread,
Apr 3, 2006, 3:30:33 AM4/3/06
to
"Andrei Alexandrescu (See Website For Email)"
<SeeWebsit...@erdani.org> wrote:
>Herb Sutter wrote:
>> In my opinion, it would absolutely be wrong to conflate where/how
>> instances a type is allocated (e.g., gc vs. non-gc) with the kind
>> of type
>> it is. This is a mistake that the Managed Extensions made, and that
>> C++/CLI corrected.
>
>That blows one of my tenets in the air. Could you please summarize what
>the experience with the Managed Extensions has shown, that revealed it's
>a mistake to conflate storage regime with the type?

Greetings from Berlin -- I'm on the road for a month, and it's hard to
make it fit into a brief article, so I'll mostly post references. :-)

>And, how does C++/CLI achieve type safety in the presence of both
>destructors and garbage collection?

Note that many Java and .NET types _do_ have destructors already -- but in
Java and C# they're just implemented using a Dispose() coding convention
rather than with direct language and runtime support. And therefore in
Java and C# they suffer from all the drawbacks of relying on programming
conventions, including that the pattern varies, people can make mistakes
such as not cascading Dispose() to what in C++ are 'directly held members'
(other disposable objects that are privately held within the
implementation of a larger disposeable object).

Here are some references:

A Design Rationale for C++/CLI
http://www.gotw.ca/publications/C++CLIRationale.pdf
Note sections 3.1.3.1, 3.1.3.3., (maybe 3.1.4.1), and all of 3.3.

"Destructors vs. GC? Destructors + GC!" (my blog, Nov 23, 2004)
http://pluralsight.com/blogs/hsutter/archive/2004/11/23/3666.aspx

"C++ RAII compared with Java Dispose pattern" (my blog, July 31, 2004)
http://blogs.gotdotnet.com/hsutter/archive/2004/07/31/203137.aspx

And in particular if you have a few minutes, see the relevant section of
this talk video (if you have a player that can show it):

OOPSLA keynote: Concrete Languages on Virtual Platforms
http://msdn.microsoft.com/visualc/using/multimedia/oopsla/default.aspx
Note in particular slides 11, 13, and 15-25.


>Something's gotta give; you could
>either leak resources, have zombie objects, or risk dangling pointer
>accesses. I couldn't find a better way than associating the regime with
>the type, and I'd be interested on how C++/CLI addressed this issue.
>
>My current understanding is that C++/CLI can leak resources no matter
>how they are designed.

I'm not sure what you mean.

>If that's the case, I will surmise that my design
>is better.
>
>Andrei

---
Herb Sutter (www.gotw.ca) (www.pluralsight.com/blogs/hsutter)

Convener, ISO WG21 (C++ standards committee) (www.gotw.ca/iso)
Architect, Developer Division, Microsoft (www.gotw.ca/microsoft)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Wu Yongwei

unread,
Apr 3, 2006, 3:39:27 PM4/3/06
to
Nemanja Trifunovic wrote:
> Wu Yongwei wrote:
>> On a new server box,
>> the Java test code to calculate prime numbers is nearly as fast as
>> the
>> identical C++ code! Of course it does not happen on my old laptop.
>
>
> That's one of the biggest problems I have with benchmarks: most of
> them
> compute prime numbers or fibonacci numbers or do something else that
> has no relevance for the real-life applications speed.

We all know in real worlds Java are slower. But the benchmarks proved
one thing: the processor time can be very small. What is not measured,
I believe, is the the time consumed in swapping virtual memory. This is
really the real difference: all GC costs more memory; most real-world
client machines have not enough memory; and thus GC'd languages are
generally weak in performance on client-side applications, but might be
OK in server boxes with a huge amount of memory.

In an economic point of view, it makes sense too. Java is useful esp.
for custom server applications, since the reduced cost of development
is more than the money one will spend on memory. On the client side,
since the audience is very big, it makes sense to spend more
development resource reducing the memory footprint by some `better'
languages like C++ :-). Maybe excepting the case where people do not
mind spending big bucks on the hardware, because the software is even
dearer, like the IBM Rational suite.

Best regards,

Yongwei

Mirek Fidler

unread,
Apr 3, 2006, 3:37:15 PM4/3/06
to
Herb Sutter wrote:

>> My current understanding is that C++/CLI can leak resources no matter
>> how they are designed.
>
>
> I'm not sure what you mean.

There is one thing I am unable to grasp for sure from C++/CLI
descriptions:

When and how is called destructor for object on GC heap?

My understanding is that it is invoked by finalizer (via Dispose?) -
which I believe is what Andrei describes as "zombie object" (a kind of
resource leak).

Mirek

Andrei Alexandrescu (See Website For Email)

unread,
Apr 4, 2006, 2:55:31 AM4/4/06
to
Herb Sutter wrote:
> Note that many Java and .NET types _do_ have destructors already -- but in
> Java and C# they're just implemented using a Dispose() coding convention
> rather than with direct language and runtime support. And therefore in
> Java and C# they suffer from all the drawbacks of relying on programming
> conventions, including that the pattern varies, people can make mistakes
> such as not cascading Dispose() to what in C++ are 'directly held members'
> (other disposable objects that are privately held within the
> implementation of a larger disposeable object).
[snip references]

Greetings from back home, Herb :o). I see. Thanks for the references
(I've actually perused them!)

So my current understanding of how C++/CLI reconciles destruction with
deterministic finalization is as follows:

- There are two kinds of classes, value and reference.

- A value type can't define a destructor? (unsure about that)

- A ref class that defines a destructor automatically inherits IDispose
and defines Dispose() appropriately.

- Even when apparently allocated on the stack, ref classes live on the
gc heap.

- ref classes will be always destroyed the C++ way (as automatic objects
or by using delete) and their memory collected the GC way - nicely
separating the two issues.

I will make the following statements, and please let me know if they are
correct:

* You can't allocate a ref type on the stack

* You can save a reference to an object that has been Dispose()d. This
is an issue akin to the much-discussed "zombie object" problem. True,
C++/CLI doesn't consider Dispose()d objects in any way less vigorous
than other objects, but there is something to be said about using a
reference to an object that was technically destroyed.

* No matter how a class was designed, the user can use it in a way that
leaks resources, e.g. by allocating it with new and then forgetting to
call delete.

My design has the following features:

- There are two kinds of classes, deterministic and collected

- Any object can live on the stack, and it is statically enforced that a
reference to a stack object cannot escape the scope in which it was defined

- References to deterministic objects are automatically
reference-counted, such that when the last live reference to a
deterministic object goes out of scope, the object is destroyed. Note
that the memory in which the object lived can actually be garbage
collected (i.e., deterministic and collected objects can share the same
heap), but that's not a must because there's demonstrably no way to
reach that memory.

I will make two statements about my design:

* With few restrictions, you still benefit of the speed of stack
allocation for all kinds of objects.

* There is no zombie issue at all

* A class designer can design a class that will deterministically
release the resource it allocated, without asking for any usage rules.
The only case in which user code can leak resources is if it saves
references in global structures.

So the above illustrates some advantages of my design over C++/CLI's. Of
course, I gloss over some little details such as:

- C++/CLI integrates with the CLI architecture and as such has different
goals and constraints;

- C++/CLI has been implemented and works.

:o)

Andrei Alexandrescu (See Website For Email)

unread,
Apr 4, 2006, 3:18:08 AM4/4/06
to
In-Reply-To: <49cpskF...@individual.net>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Mirek Fidler wrote:
> Herb Sutter wrote:
>
>
>>>My current understanding is that C++/CLI can leak resources no matter
>>>how they are designed.
>>
>>
>>I'm not sure what you mean.
>
>
> There is one thing I am unable to grasp for sure from C++/CLI
> descriptions:
>
> When and how is called destructor for object on GC heap?
>
> My understanding is that it is invoked by finalizer (via Dispose?) -
> which I believe is what Andrei describes as "zombie object" (a kind of
> resource leak).

I was not referring to zombies, although my current understanding is
that C++/CLI allows them, and the recent thread "can GC be beneficial"
made me understand that zombies are an undesirable artifact to have in a
language. Here's a success story of the Usenet: somebody got convinced
of something :o).

I was referring to the following - in my design, if you say:

class [deterministic] File { ... };

then File provides a strong guarantee that as soon as the last reference
to a File disappears from its scope, the underlying file will be closed.
This is a very useful guarantee; it takes destructors, RAII, and all
of their benefits to an entirely new level. Because today all you have
to thwart RAII is to allocate objects on the heap (most often indirectly
and thus in hard-to-detect setups). My design says that no matter how
the File is used, when you're done using it, it will be closed.

The remaining risk is that someone keeps a reference to a File buried
somewhere in a long-lasting structure. Current technology has no
solution for that kind of leak. We could just as well discuss possible
ways to adress this issue here.

Andrei

Edward Diener No Spam

unread,
Apr 5, 2006, 3:49:01 AM4/5/06
to
Andrei Alexandrescu (See Website For Email) wrote:
> Herb Sutter wrote:
>> Note that many Java and .NET types _do_ have destructors already -- but in
>> Java and C# they're just implemented using a Dispose() coding convention
>> rather than with direct language and runtime support. And therefore in
>> Java and C# they suffer from all the drawbacks of relying on programming
>> conventions, including that the pattern varies, people can make mistakes
>> such as not cascading Dispose() to what in C++ are 'directly held members'
>> (other disposable objects that are privately held within the
>> implementation of a larger disposeable object).
> [snip references]
>
> - C++/CLI has been implemented and works.

It does not automatically work for the case in which one wants to pass
around objects of a ref class which needs to have its resources released
when it is no longer being referenced. In this regard C++/CLI is not the
only culprit, since this problem is the same for other GC languages like
Java, Python, and Ruby. None of them have solved the problem, unless the
solution is "don't do that" <g> or manually figure out somehow when to
release resources of the object on a case by case basis. I wanted to
make the point that all of these very popular GC languages have either
largely ignored the problem of deterministic disposal of resources or
limited the ways in which one can use such an object.

That is why I support that part of your proposal which attempts to solve
the problem of the deletion of deterministic objects in a GC/C++ system,
and to use the same syntax for dealing with both deterministic and
collected objects. A C++ GC system must not settle for the limitations,
regarding deterministic types, of other GC systems as they now exist.

Herb Sutter

unread,
Apr 5, 2006, 3:45:16 AM4/5/06
to
Caveat: What I wrote below probably isn't very coherent because I have a
cold and I'm writing it with only half attention while in a meeting. (So
sorry if this is fuzzy or unclear!)

"Andrei Alexandrescu (See Website For Email)"

<SeeWebsit...@erdani.org> wrote:
>Herb Sutter wrote:
>> Note that many Java and .NET types _do_ have destructors already -- but in
>> Java and C# they're just implemented using a Dispose() coding convention
>> rather than with direct language and runtime support. And therefore in
>> Java and C# they suffer from all the drawbacks of relying on programming
>> conventions, including that the pattern varies, people can make mistakes
>> such as not cascading Dispose() to what in C++ are 'directly held members'
>> (other disposable objects that are privately held within the
>> implementation of a larger disposeable object).
>[snip references]
>
>Greetings from back home, Herb :o). I see. Thanks for the references
>(I've actually perused them!)

Thanks. I'll respond to your detailed questions below, but to summarize
it, the idea is:

- a type can have a destructor and/or a finalizer
- the destructor is called upon a) explicit delete or b) at end of scope
for auto objects
- the finalizer is called if allocated on the gc heap and the destructor
has not been called

The usual guidance to avoid some code duplication between the destructor
and finalizer is: Have the finalizer hold all the teardown code that can
go into the finalizer, and have the destructor hold the rest of the
teardown code and then call the finalizer.

>So my current understanding of how C++/CLI reconciles destruction with
>deterministic finalization is as follows:
>
>- There are two kinds of classes, value and reference.

But note that's a red herring and not really relevant to this discussion.
A value type is basically a POD (memcpyable, trivial dtor).

>- A value type can't define a destructor? (unsure about that)

A value type can't have a user-defined dtor, so consider it to always have
a trivial dtor. (A value type can have a finalizer.)

>- A ref class that defines a destructor automatically inherits IDispose
>and defines Dispose() appropriately.

Yes.

>- Even when apparently allocated on the stack, ref classes live on the
>gc heap.

Yes. Note that this isn't inherent in C++/CLI at the language level, it's
just an implementation detail because CLI happens to require this object
placement.

>- ref classes will be always destroyed the C++ way (as automatic objects
>or by using delete) and their memory collected the GC way - nicely
>separating the two issues.

Yes. But this applies to all types, not just ref classes but also value
classes (which have a trivial dtor) and C++ types (de jure).

>I will make the following statements, and please let me know if they are
>correct:
>
>* You can't allocate a ref type on the stack

You can do that semantically (i.e., you can write that code). Physically
the compiler will place it on the gc heap.

>* You can save a reference to an object that has been Dispose()d. This
>is an issue akin to the much-discussed "zombie object" problem. True,
>C++/CLI doesn't consider Dispose()d objects in any way less vigorous
>than other objects, but there is something to be said about using a
>reference to an object that was technically destroyed.

Just like today you can have a pointer to an object that has been
destroyed or deleted, yes.

>* No matter how a class was designed, the user can use it in a way that
>leaks resources, e.g. by allocating it with new and then forgetting to
>call delete.

That's the intent, although C++/CLI doesn't yet support "new R" or "new V"
(allocating a reference type semantically on the C++ heap).

>My design has the following features:
>
>- There are two kinds of classes, deterministic and collected
>
>- Any object can live on the stack, and it is statically enforced that a
>reference to a stack object cannot escape the scope in which it was defined

Statically enforced for any object? What if you have to call an API and
pass the address of a stack variable? Example:

char src[] = "xyzzy", dst[80];
strcpy( dst, src );

Now we happen to know strcpy (probably) doesn't save copies of the
pointers. But in general we don't know whether called function will
squirrel away a copy of any pointer arguments we give it. Are you planning
to address that, and if so how? Another example:

int value;
LoadValueFromDisk( &value );

I think that needs to be legal for compatibility, but we don't know if the
pointer has escaped. Would you allow this, ban it, deal with it some other
way, or...?

>- References to deterministic objects are automatically
>reference-counted, such that when the last live reference to a
>deterministic object goes out of scope, the object is destroyed. Note
>that the memory in which the object lived can actually be garbage
>collected (i.e., deterministic and collected objects can share the same
>heap), but that's not a must because there's demonstrably no way to
>reach that memory.

How do you deal with cycles? For a simple example:

class [deterministic] ListNode {
ListNode * prev, *next;
...
};

Am I allowed to write that? Even if not, what about other cases where we
can't know whether a cycle can occur until runtime?

>I will make two statements about my design:
>
>* With few restrictions, you still benefit of the speed of stack
>allocation for all kinds of objects.

Not sure what speed you're referring to here, but if you mean that ref
class objects are physically allocated on the gc heap, no worries; it's
two instructions. And it's just an implementation detail of CLI that this
needs to be done under the covers, it's not part of the C++/CLI language
extensions design w.r.t. dtors and fzers.

>* There is no zombie issue at all

Sure, ref counting works is great when it's applicable. Of course, most
real-world ref counting schemes don't do the ref count updates
synchronously, they batch them up, which means you either get synchronous
destruction at a performance cost, or you don't get synchronous
destruction even with ref counting (which is bad because it's desirable to
know when the dtor runs if it's running on a program thread, e.g., life is
bad if a) the dtor run on an app thread, b) the dtor takes a lock, and c)
you don't know when the dtor will run).

>* A class designer can design a class that will deterministically
>release the resource it allocated, without asking for any usage rules.
>The only case in which user code can leak resources is if it saves
>references in global structures.

I'd like to see how well it fares w.r.t. the above questions. I have
others too, but those are the first to come to mind sitting here in an EWG
meeting talking about memory models and atomic operations. :-)

Herb

Convener, ISO WG21 (C++ standards committee) (www.gotw.ca/iso)
Architect, Developer Division, Microsoft (www.gotw.ca/microsoft)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Nevin ":-]" Liber

unread,
Apr 5, 2006, 3:55:43 AM4/5/06
to
In article <4431DB2F...@erdani.org>,

"Andrei Alexandrescu (See Website For Email)"
<SeeWebsit...@erdani.org> wrote:

> class [deterministic] File { ... };
>
> then File provides a strong guarantee that as soon as the last reference
> to a File disappears from its scope, the underlying file will be closed.
> This is a very useful guarantee; it takes destructors, RAII, and all
> of their benefits to an entirely new level. Because today all you have
> to thwart RAII is to allocate objects on the heap (most often indirectly
> and thus in hard-to-detect setups). My design says that no matter how
> the File is used, when you're done using it, it will be closed.

Does this mean that a File variable cannot be a member of either a C++98
class or a collected class?

Otherwise, I'm not seeing how that guarantee is any stronger than
anything we have today, as I can trivially wrap a File in another class
that I then allocate on the heap.

new basically has three purposes:
1) Polymorphism
2) Lifetime management different than its enclosing scope
3) Object "too big" for the stack frame

It seems like all you are doing is separating 1 and 2, and adding that
responsibility to the class instead of keeping that concern separate.
Is that a valid assessment?

--
Nevin ":-)" Liber <mailto:ne...@eviloverlord.com> (773) 961-1620

Nevin ":-]" Liber

unread,
Apr 5, 2006, 3:55:16 AM4/5/06
to
In article <44315E8...@erdani.org>,

"Andrei Alexandrescu (See Website For Email)"
<SeeWebsit...@erdani.org> wrote:

> - References to deterministic objects are automatically
> reference-counted, such that when the last live reference to a
> deterministic object goes out of scope, the object is destroyed. Note
> that the memory in which the object lived can actually be garbage
> collected (i.e., deterministic and collected objects can share the same
> heap), but that's not a must because there's demonstrably no way to
> reach that memory.

How does this differ than tr1::shared_ptr, other than having the class
manage its own lifetime instead of separating that concern? Does it
have the same drawbacks with respect to cycles?

--
Nevin ":-)" Liber <mailto:ne...@eviloverlord.com> (773) 961-1620

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Raoul Gough

unread,
Apr 5, 2006, 8:28:41 AM4/5/06
to
Mirek Fidler wrote:
> >>>>I do not like idea of my code freezing for a moment at random
> >>>>time...
> >
> >> You mean like when the last smart pointer to a chain of objects
> >> is dropped.
>
> Using reference counting smart pointers is just another bad idea...

I know there are some issues with using reference counting, but I don't
think I've seen them dismissed outright as a "bad idea" before. What
badness are you referring to, and what are the superior options?

--
Raoul Gough.

Larry

unread,
Apr 5, 2006, 8:29:10 AM4/5/06
to
On 04/05/2006 02:55 AM, Nevin ":-]" Liber wrote:
> In article <44315E8...@erdani.org>,
> "Andrei Alexandrescu (See Website For Email)"
> <SeeWebsit...@erdani.org> wrote:
[snip]

>>- References to deterministic objects are automatically
>>reference-counted, such that when the last live reference to a
[snip]

> manage its own lifetime instead of separating that concern? Does it
> have the same drawbacks with respect to cycles?

Yes, as Andrei says in post 139 here:

http://tinyurl.com/q3nyn

Niklas Matthies

unread,
Apr 5, 2006, 8:39:12 AM4/5/06
to
On 2006-04-05 07:45, Herb Sutter wrote:
[C++/CLI]

> - a type can have a destructor and/or a finalizer
> - the destructor is called upon a) explicit delete or b) at end
> of scope
> for auto objects
> - the finalizer is called if allocated on the gc heap and the
> destructor
> has not been called
>
> The usual guidance to avoid some code duplication between the
> destructor
> and finalizer is: Have the finalizer hold all the teardown code
> that can
> go into the finalizer, and have the destructor hold the rest of the
> teardown code and then call the finalizer.

How does this work with regard to base/derived classed?
Doesn't this cause the (most-derived?) finalizer to be invoked N times
by the N destructor bodies?

-- Niklas Matthies

Mirek Fidler

unread,
Apr 6, 2006, 2:58:24 AM4/6/06
to
Raoul Gough wrote:

>>Using reference counting smart pointers is just another bad idea...
>
>
> I know there are some issues with using reference counting, but I don't
> think I've seen them dismissed outright as a "bad idea" before. What
> badness are you referring to, and what are the superior options?

Let me make it clear: It is bad idea _IMO_.

I not only believe, but I dare to say that I _know_ that much better
_unrestricted_ (by current "know-how" and "coding-standards") solution
to the problem is to avoid value semantics in containers and use
deterministic owning (but not copying!) containers with perhaps a little
bit of moving semantics.

In other words, need for GC in C++ indicates large scale failure of STL
design concepts.

Smart pointers, in this regard, are just partly succesful attempt to
simulate GC using the current language facilities.

IME, using deterministic style with owning containers results in very
clean, compact and fast code - tested across very diverse set of real
world applications (if you mind, you can follow this link to see some
examples:

http://upp.sourceforge.net/www$uppweb$apps$en-us.html

).

Mirek

Andrei Alexandrescu (See Website For Email)

unread,
Apr 6, 2006, 2:59:39 AM4/6/06
to
Herb Sutter wrote:
[skip discussion on C++/CLI; agreement on all points]

>>My design has the following features:
>>
>>- There are two kinds of classes, deterministic and collected
>>
>>- Any object can live on the stack, and it is statically enforced that a
>>reference to a stack object cannot escape the scope in which it was defined
>
>
> Statically enforced for any object? What if you have to call an API and
> pass the address of a stack variable? Example:
>
> char src[] = "xyzzy", dst[80];
> strcpy( dst, src );

Aha, so I can tell someone hasn't read my post describing what happens
:o). That feature is the "auto" pointer qualifier, which in essence
works like this: if you take the address of a stack variable of type T,
that address has type T *auto. So:

char str[100];
char * p1 = str; // error
char *auto p2 = str; // fine

The signature of strcpy must be changed to:

char *auto strcpy(char *auto dst, const char *auto src);

This one signature will work for everything because char* is convertible
to char*auto.

Changing the signature can be done wholesale on the entire C API because
all of its functions do NOT squirrel away user pointers, with a few well
known exceptions that are infamous for their lack of thread safety
(e.g., strtok). So I don't see that as a major problem.

Other APIs need declaration changes as well, and that is a larger-scale
problem.

> Now we happen to know strcpy (probably) doesn't save copies of the
> pointers. But in general we don't know whether called function will
> squirrel away a copy of any pointer arguments we give it. Are you planning
> to address that, and if so how? Another example:
>
> int value;
> LoadValueFromDisk( &value );
>
> I think that needs to be legal for compatibility, but we don't know if the
> pointer has escaped. Would you allow this, ban it, deal with it some other
> way, or...?

Compatibility was not one main goal of my design. I focused on hard
guarantees and devised the least restrictive set of rules that respects
them. This is a very useful point in the design space because it has no
gratuitous restrictions, has useful properties, and makes it easy to
assess exactly what are the consequences of each departure for the sake
of compatibility. I see problems of functions not declaring *auto when
they should, similar to the infamous conversion from const char[N] to
char* of literal strings. We all know it's totally senseless, but it's
in the language for the sake of compatibility.

>>- References to deterministic objects are automatically
>>reference-counted, such that when the last live reference to a
>>deterministic object goes out of scope, the object is destroyed. Note
>>that the memory in which the object lived can actually be garbage
>>collected (i.e., deterministic and collected objects can share the same
>>heap), but that's not a must because there's demonstrably no way to
>>reach that memory.
>
>
> How do you deal with cycles? For a simple example:
>
> class [deterministic] ListNode {
> ListNode * prev, *next;
> ...
> };
>
> Am I allowed to write that? Even if not, what about other cases where we
> can't know whether a cycle can occur until runtime?

You are allowed to write that, and it might leak resources if cycles are
involved. Deterministic objects are marred by the same problems as their
underlying reference counting - I designed a language artifact, not a
perpetuum mobile :o).

The idea of using my system is that only a precious few objects will be
deterministic, and most others will be collected. The validity of this
assumption is sustained by the observation that most of today's
destructors cleanup memory, and only an important minority of objects
handle other resources. My design allows you to carefully design those
few objects in ways that provide hard guarantees.

>>I will make two statements about my design:
>>
>>* With few restrictions, you still benefit of the speed of stack
>>allocation for all kinds of objects.
>
>
> Not sure what speed you're referring to here, but if you mean that ref
> class objects are physically allocated on the gc heap, no worries; it's
> two instructions.

We've been over that in a private conversations, and I think this is
only part of the story. Fast allocators have gruesome locality and eat
more memory. Yes, two instructions that bump the frontier of the used
memory yet some more! Do that in a loop and you'll be very unhappy very
soon. In contrast, stack allocation is technically amortized free - the
amount of needed stack for a function is computed statically, and the
appropriate SP decrease is done upon entering the function. Furthermore,
optimizing compilers squeeze down the amount of stack needed by
analyzing mutually exclusive lifetimes, e.g.:

void foo() {
if (x) {
char bar[90];
...
} else {
char baz[120];
}
}

This function's stack space is 120, not 210. I know gcc has had this
optimization for a while, while VC 6 didn't have it.

To conclude the "two instructions" issue, I think we're still at a point
in history where stack allocation is significantly faster. I agree the
gap has narrowed, but it's not negligible at all in the codes I play
with, and I believe in many other applications.

> And it's just an implementation detail of CLI that this
> needs to be done under the covers, it's not part of the C++/CLI language
> extensions design w.r.t. dtors and fzers.

I agree. My point was that my design catered for stack variables in a
type-safe way, and did that because I assume that stack allocation is
still important.

>>* There is no zombie issue at all
>
>
> Sure, ref counting works is great when it's applicable. Of course, most
> real-world ref counting schemes don't do the ref count updates
> synchronously, they batch them up, which means you either get synchronous
> destruction at a performance cost, or you don't get synchronous
> destruction even with ref counting (which is bad because it's desirable to
> know when the dtor runs if it's running on a program thread, e.g., life is
> bad if a) the dtor run on an app thread, b) the dtor takes a lock, and c)
> you don't know when the dtor will run).

My design would do (at face value) just what a well-done intrusive smart
pointer does today. The compiler can further optimize away some needless
++/--, but that's about it.

Again, I believe this is a good balance because smart pointers today
*are* being used today, and much more intensively given that there's no
alternative (GC). In my system, you'd only use deterministic types for a
few resources, use collected types for all others, and smile all the way
to the bank. Ahem.

>>* A class designer can design a class that will deterministically
>>release the resource it allocated, without asking for any usage rules.
>>The only case in which user code can leak resources is if it saves
>>references in global structures.
>
>
> I'd like to see how well it fares w.r.t. the above questions. I have
> others too, but those are the first to come to mind sitting here in an EWG
> meeting talking about memory models and atomic operations. :-)

Shoot. :o)


Andrei

kanze...@neuf.fr

unread,
Apr 6, 2006, 2:54:21 AM4/6/06
to
Nemanja Trifunovic wrote:
> Wu Yongwei wrote:

> > On a new server box, the Java test code to calculate prime
> > numbers is nearly as fast as the identical C++ code! Of
> > course it does not happen on my old laptop.

> That's one of the biggest problems I have with benchmarks:
> most of them compute prime numbers or fibonacci numbers or do
> something else that has no relevance for the real-life
> applications speed.

It depends on the benchmarks. People doing numerics have
developed some significant benchmarks. For their applications;
they don't tell me much about the performance of a system for my
applications. Part of the reason is probable because that raw
CPU power is the bottleneck in a lot of numeric applications.

For the rest, I tend to agree. Depending on how it is written,
there's a very, very good chance that the garbage collection
never runs in a prime number benchmark. And that the execution
speed of malloc/free is probably irrelevant to the versions not
using garbage collection. So whatever else the benchmark might
tell us (which IMHO probably isn't much), it says nothing about
the relative speeds of garbage collection and manual memory
management.

--
James Kanze

kanze...@neuf.fr

unread,
Apr 6, 2006, 2:55:37 AM4/6/06
to
Wu Yongwei wrote:
> We all know in real worlds Java are slower.

And we all know that the world is flat. It depends on the
applciation and the implementation. There are applications
where the Java replacement was faster than the original C++ --
while offering more features.

> But the benchmarks proved one thing: the processor time can be
> very small. What is not measured, I believe, is the the time
> consumed in swapping virtual memory. This is really the real
> difference: all GC costs more memory; most real-world client
> machines have not enough memory; and thus GC'd languages are
> generally weak in performance on client-side applications, but
> might be OK in server boxes with a huge amount of memory.

It depends on what you mean by "not enough memory". Garbage
collection does require more memory, but if it is run often
enough, it doesn't require that much more. On a PC client, it
is usual for garbage collection to run whenever the program is
waiting for user input. That's often enough that the extra
memory requirements are negligeable. Note that this does mean
that the garbage collector uses more CPU than it would
otherwise. But since it does so when the CPU is not needed for
anything else.

In every case, the actual evaluation as to what's important will
depend on the application. The applications I've done lately
have mostly been large scale servers, with one GUI framework.
In all of the cases, except maybe one, garbage collection would
have been a big win, in the sense that it would have improved
my productivity without causing performance problems (which in
the servers, was a critical issue). Many years ago, I worked on
critical, embedded systems on very small processors -- there,
even dynamic memory was banned.

--
James Kanze

kanze...@neuf.fr

unread,
Apr 6, 2006, 6:14:10 AM4/6/06
to
David Abrahams wrote:
> "kanze" <ka...@gabi-soft.fr> writes:


> >> I find it curious that this "performance" problem with g++
> >> only appeared when it was mentionned that g++ uses garbage


> >> collection. Before this week, I'd always heard the
> >> reverse.

I don't.

> Appendix C contains the graphs showing how much slower g++ is
> at template instantiation than VC++.

That could easily explain the differences. While the code I
used to test does use templates in some places, it certainly
doesn't use them as extensively as Boost.

--
James

kanze...@neuf.fr

unread,
Apr 6, 2006, 6:15:07 AM4/6/06
to
Wu Yongwei wrote:
> kanze wrote:

> > Nemanja Trifunovic wrote:
> > > kanze wrote:

> > > > Also, even today, g++ does compare favorably with the
> > > > two other compilers I hae access to: VC++ and Sun CC.
> > > > The Windows version that I'm using is somewhat slower
> > > > that VC++, probably because of the CygWin layering, but
> > > > the Linux version is significantly faster. (In neither
> > > > case, however, is the difference anything to get excited
> > > > about. Nothing like the slowdowns I experienced with
> > > > both Sun CC and g++ when upgrading to "conformant"
> > > > compilers.)

> > > You must be kidding. g++ is slower than any version of
> > > VC++ I've ever worked with (even VC2005 which has
> > > ridiculous link time).

> > I just measured it. Under Windows, g++ 3.3.3 (cygwin
> > special) is a little less than 20% slower than VC++ 2005,
> > for exactly the same build (making both debug and optimized
> > versions of a number of libraries, plus the unit tests).

> > The same build with g++ under Linux is about 30% faster than
> > VC++ under windows.

> Just a guess, but I think your machine must have a big amount
> of memory (512 MB or bigger). I believe GCC (esp. the new
> versions) eats a lot more memory than VC++.

I think it had 256 MB, but I'm not sure (and I'm in Berlin at
the moment, so I cannot verify it).

I think David's explination is perhaps more pertinant; VC++ is
faster than g++ at some things, not at others. My code base
happens to make much less use of the things at which g++ is
slower than some other code bases. My feed back from others,
too, is mainly from application programmers, often compiling
older code -- with in most cases, very few templates. (When you
wrote code targeting VC++ 6.0, you didn't make intensive use of
advanced template features.)

> I did not know that GCC uses GC. However, this quite makes
> sense now. Really, Java is not slow on big-memory machines.


> On a new server box, the Java test code to calculate prime
> numbers is nearly as fast as the identical C++ code! Of course
> it does not happen on my old laptop.

That's a point worth pointing out. GC often does require more
memory. So do some uses of std::vector:-). Any proposed
standard garbage collection must make it optional, for the times
when, for whatever reasons, it's not appropriate (or you simply
don't want it).

--
James Kanze

Martin Aupperle

unread,
Apr 6, 2006, 11:08:05 AM4/6/06
to
On 5 Apr 2006 03:49:01 -0400, Edward Diener No Spam
<eldiener_n...@earthlink.net> wrote:

>
>It does not automatically work for the case in which one wants to pass
>around objects of a ref class which needs to have its resources released
>when it is no longer being referenced. In this regard C++/CLI is not the
>only culprit, since this problem is the same for other GC languages like
>Java, Python, and Ruby. None of them have solved the problem, unless the
>solution is "don't do that" <g> or manually figure out somehow when to
>release resources of the object on a case by case basis. I wanted to
>make the point that all of these very popular GC languages have either
>largely ignored the problem of deterministic disposal of resources or
>limited the ways in which one can use such an object.

Worse: They not only have ignored it, many C# (and I guess Java too)
programmers simply are not aware of the problem. I many times heard
arguments like "this is old C++ thinking! We don't need deterministic
finalization because the GC cleans up!". Unbelievable? It's true.

- Martin

Paavo

unread,
Apr 6, 2006, 11:10:26 AM4/6/06
to

kanze wrote:

> I just measured it. Under Windows, g++ 3.3.3 (cygwin special)

> is a little less than 20% slower than VC++ 2005.

Well, I just made a test, on a Windows machine, using VC++ 2003 and
CygWin GCC 3.4.4 (cygming special):

WS14: MemBlock>wc -l vector.cpp
4097 vector.cpp

WS14: MemBlock>grep -c template vector.cpp
110

WS14: MemBlock>time cl /c /O2 /EHa vector.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for
80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

vector.cpp

real 0m13.694s
user 0m0.020s
sys 0m0.170s


WS14: MemBlock>time g++ -c -O3 vector.cpp

real 0m57.678s
user 0m55.529s
sys 0m1.370s


The machine is 1.4GHz, 2 gigs of RAM, no trashing, commands repeated
several times, etc. So it appears that for heavily templated code g++
is about 4 times slower. For non-templated code the ratio was better,
g++ was about 2 times slower.

HTH
Paavo

kanze...@neuf.fr

unread,
Apr 7, 2006, 3:29:59 AM4/7/06
to
Mirek Fidler wrote:
> >> But "on average" doesn't tell the whole story. "Stop the
> >> world" pauses can be a problem if, for example, you have to
> >> consistently deliver 25 frames per second, or you have a
> >> thread that must not be stopped.

> > For that particular example, there is a simple solution --
> > force it to run after each frame is delivered. It will run
> > in the

> Nope. Modern games are 512MB+ beasts. Top raw memory bandwidth
> is ~5GB/s. There is no way how you could do 25 mark phases
> of 512MB per second.

There certainly aren't 512MB of pointers. You only have to scan
memory which can potentially contain pointers.

With current C++, you have to indicate the absence of pointers
explicitly (and manually). If GC were standard, at least
according to the proposal before the committee, the compiler
could generate the necessary notation.

--
James Kanze

kanze...@neuf.fr

unread,
Apr 7, 2006, 3:31:52 AM4/7/06
to
Peter Dimov wrote:
> kanze wrote:
> > Mirek Fidler wrote:
> > > > There's something called generational garbage
> > > > collection. I've

> > > Of course. But inevitably, even with generational garbage
> > > collection, there must (or should) be times when complete
> > > mark phase has to happen.

> > > I do not like idea of my code freezing for a moment at
> > > random time...

> > You mean like when the last smart pointer to a chain of

> > objects is dropped. Whether you like it or not, practically
> > speaking, as soon as the destructor of one object can
> > trigger destruction of another object, you've got it. The
> > only way to avoid it is to avoid non-trivial destructors,
> > and that's a price I'm not willing to pay.

> This can be a problem in real time applications, but:

> - it only stalls the current thread;
> - it's relatively easy to avoid. Just move the pointer to a 'destroy
> queue' instead and clear the queue at appropriate times.

In other words, do manually what well used garbage collection
does automatically.

> > There are real time garbage collectors with guaranteed
> > latency, if that's what you need.

> It is my current understanding that all known real time
> collectors require compiler support. They need extra code on
> every pointer load, every pointer store, or both.

Possibly. I know that they exist, and I know that they require
more total time (on the average, at least) than collectors which
don't give a latency guarantee. I don't know any more -- since
in all of my applications, I'm more concerned with lower total
time, I didn't look any further in this direction. (There's
also the fact that the Boehm collector doesn't guarantee
latency, and is much more readily available than anything else.)

Niklas Matthies

unread,
Apr 7, 2006, 4:12:12 AM4/7/06
to
On 2006-04-06 06:59, Andrei Alexandrescu (See Website For Email) wrote:
> Herb Sutter wrote:
:

>> What if you have to call an API and
>> pass the address of a stack variable? Example:
>>
>> char src[] = "xyzzy", dst[80];
>> strcpy( dst, src );
>
> Aha, so I can tell someone hasn't read my post describing what happens
> :o). That feature is the "auto" pointer qualifier, which in essence
> works like this: if you take the address of a stack variable of type T,
> that address has type T *auto. So:
>
> char str[100];
> char * p1 = str; // error
> char *auto p2 = str; // fine
>
> The signature of strcpy must be changed to:
>
> char *auto strcpy(char *auto dst, const char *auto src);
:

> Other APIs need declaration changes as well, and that is a
> larger-scale problem.

That doesn't scale at all. For example

void f(T * auto ptr)
{
some_stl_algo(foo, boost::bind(bar, ptr));
}

won't work because the 'bind' functor isn't allowed to store the auto
pointer. Same here:

void f(Database * auto db)
{
db->connect();
ON_BLOCK_EXIT(db, &Database::disconnect);
perform_transaction(db);
}

Or if you want to do

void f(Database * auto db)
{
DBConnection conn(db);
perform_transaction(conn);
}

how can 'conn' hold a reference to 'db'?

-- Niklas Matthies

Mirek Fidler

unread,
Apr 7, 2006, 5:48:32 AM4/7/06
to
>>>For that particular example, there is a simple solution --
>>>force it to run after each frame is delivered. It will run
>>>in the
>
>
>>Nope. Modern games are 512MB+ beasts. Top raw memory bandwidth
>>is ~5GB/s. There is no way how you could do 25 mark phases
>>of 512MB per second.
>
>
> There certainly aren't 512MB of pointers. You only have to scan
> memory which can potentially contain pointers.

Actually, it is enough that there is single pointer per 64 bytes -
smallest memory quantum ("cache-line").

> With current C++, you have to indicate the absence of pointers
> explicitly (and manually). If GC were standard, at least
> according to the proposal before the committee, the compiler
> could generate the necessary notation.

Even with reinterpret_casts? ;) I still do not see how you could
integrate non-conservative GC with C++ that would behave correctly with
the current code...

Mirek

Niklas Matthies

unread,
Apr 7, 2006, 5:44:49 AM4/7/06
to
On 2006-04-06 06:59, Andrei Alexandrescu (See Website For Email) wrote:
> Herb Sutter wrote:
:

>> What if you have to call an API and pass the address of a stack
>> variable? Example:
>>
>> char src[] = "xyzzy", dst[80];
>> strcpy( dst, src );
>
> Aha, so I can tell someone hasn't read my post describing what
> happens :o). That feature is the "auto" pointer qualifier, which in
> essence works like this: if you take the address of a stack variable
> of type T, that address has type T *auto. So:
>
> char str[100];
> char * p1 = str; // error
> char *auto p2 = str; // fine
>
> The signature of strcpy must be changed to:
>
> char *auto strcpy(char *auto dst, const char *auto src);

[In addition to my previous reply:]
Returning an auto pointer is quite interesting too.
Would the following be legal?

char * auto foo(char * auto dst)
{
return strcpy(dst, "bla");
}

Then consider:

int * auto f(int * auto p1, int auto * p2)
{
return p1; // like strcpy
}

int * auto g(int * auto p)
{
int n = 5;
return f(&n, p); // like in foo above
}

int h()
{
int m = 23;
return *g(&m); // BANG!
}

If the first example is not legal, then the use of strcpy would be
pretty restricted. More generally, auto pointers don't work well with
forwarding/abstracting functions.

-- Niklas Matthies

Matti Rintala

unread,
Apr 7, 2006, 5:49:11 AM4/7/06
to
Niklas Matthies wrote:
> Or if you want to do
>
> void f(Database * auto db)
> {
> DBConnection conn(db);
> perform_transaction(conn);
> }
>
> how can 'conn' hold a reference to 'db'?

This has been bothering me in Andrei's proposal also, but I haven't had
time to think about it lately. The auto proposal could work for simple
functions where it's easy to make sure they don't "leak" the pointer
elsewhere. But as you point out, similar mechanism would be needed inside
classes as well, and the definition of a class does not limit its lifetime
(although the lifetime of the object itself *may* be sufficiently limited,
if it's local to the function).

--
------------- Matti Rintala ------------ matti....@tut.fi ------------
Painting is the art of inclusion. Photography is an art of exclusion.

Hans Bos

unread,
Apr 7, 2006, 5:51:41 AM4/7/06
to
"Andrei Alexandrescu (See Website For Email)" <SeeWebsit...@erdani.org>
wrote in message news:4431DB2F...@erdani.org...
...

>
> The remaining risk is that someone keeps a reference to a File buried
> somewhere in a long-lasting structure. Current technology has no
> solution for that kind of leak. We could just as well discuss possible
> ways to adress this issue here.
>

So there is not much difference in using garbage collection with finalization
and reference counting.
You can't always be sure when destructors are called with reference counting.

With automatic reference counting you can still get references to destroyed
objects.
If in a constructor, you register a reference to "this" and an exception is
thrown before the constructor terminates you have a (reference counted)
reference to an incomplete (zombie) object.
The same applies when you register an object from its destructor.

If you want to force finalization of garbage collected objects (asuming you have
finalization), you can always explicitly start the garbage collection.

Hans.

Andrei Alexandrescu (See Website For Email)

unread,
Apr 8, 2006, 6:08:57 AM4/8/06
to
Niklas Matthies wrote:
> That doesn't scale at all. For example
>
> void f(T * auto ptr)
> {
> some_stl_algo(foo, boost::bind(bar, ptr));
> }
>
> won't work because the 'bind' functor isn't allowed to store the auto
> pointer. Same here:
>
> void f(Database * auto db)
> {
> db->connect();
> ON_BLOCK_EXIT(db, &Database::disconnect);
> perform_transaction(db);
> }
>
> Or if you want to do
>
> void f(Database * auto db)
> {
> DBConnection conn(db);
> perform_transaction(conn);
> }
>
> how can 'conn' hold a reference to 'db'?

The sound way to solve all of these issues is to propagate the "auto"
qualifier to members, in analogy with const.

Andrei Alexandrescu (See Website For Email)

unread,
Apr 8, 2006, 6:10:44 AM4/8/06
to
Hans Bos wrote:
> "Andrei Alexandrescu (See Website For Email)" <SeeWebsit...@erdani.org>
> wrote in message news:4431DB2F...@erdani.org...
> ...
>
>>The remaining risk is that someone keeps a reference to a File buried
>>somewhere in a long-lasting structure. Current technology has no
>>solution for that kind of leak. We could just as well discuss possible
>>ways to adress this issue here.
>>
>
>
> So there is not much difference in using garbage collection with finalization
> and reference counting.
> You can't always be sure when destructors are called with reference counting.

There is a huge difference in terms of likelihood. In my system there's
one situation that you need to be on lookout for. In current C++ there's
that and much more frequent situations you need to worry about.

> With automatic reference counting you can still get references to destroyed
> objects.
> If in a constructor, you register a reference to "this" and an exception is
> thrown before the constructor terminates you have a (reference counted)
> reference to an incomplete (zombie) object.
> The same applies when you register an object from its destructor.

Interesting. Then the type of "this" in the constructor and destructor
should be T *auto. That would, however, rule out legitimate cases.

I don't have a definitive answer to this issue.

> If you want to force finalization of garbage collected objects (asuming you have
> finalization), you can always explicitly start the garbage collection.

Which I believe is not the way to go. I don't think finalization is a
good substitute for destructors.

Andrei Alexandrescu (See Website For Email)

unread,
Apr 8, 2006, 6:10:12 AM4/8/06
to
Niklas Matthies wrote:
> [In addition to my previous reply:]
> Returning an auto pointer is quite interesting too.
> Would the following be legal?
>
> char * auto foo(char * auto dst)
> {
> return strcpy(dst, "bla");
> }

Yes, it would be legal.

> Then consider:
>
> int * auto f(int * auto p1, int auto * p2)
> {
> return p1; // like strcpy
> }

Alrighty. That's like "an identity function with an extra unused
parameter" :o). As an aside, it's amazing how many languages have
trouble implementing the identity function correctly, efficiently,
type-safely, or any combination thereof.

> int * auto g(int * auto p)
> {
> int n = 5;
> return f(&n, p); // like in foo above
> }

That is a statically-detected error. The semantics of *auto is that an
*auto of inner scope cannot be assigned to an *auto of outer scope. The
returned pointer and the incoming parameters are of the same scope
(i.e., g's call context) so you can return p, but you cannot return
f(&n, p). This is an imperfection of the type system because it
restricts more than it should. I believe ArchJava does something similar.

Things could be improved by decreeing f's return no more scoped than its
arguments. This is sound because the only *auto things that f can return
are its own arguments, or some non-automatic object (which are safe);
any fucntion doesn't have access to any other *autos.

Then, the compiler infers that the result of f(&n, p) is as restricted
as its most restricted argument, and rejects the call on that basis.
However, a call such as f(p, p) won't be restricted anymore, which is
nice. I believe this is entirely sound, but I don't know if it has been
done in an actual typesystem.

> int h()
> {
> int m = 23;
> return *g(&m); // BANG!
> }
>
> If the first example is not legal, then the use of strcpy would be
> pretty restricted. More generally, auto pointers don't work well with
> forwarding/abstracting functions.

I know *auto is sound and immensely useful as a complement to automatic
smart pointers. It's great to focus on improving its expressiveness;
thanks for your insight.


Andrei

Niklas Matthies

unread,
Apr 9, 2006, 4:53:10 AM4/9/06
to

How are you going to make 'foo' above work? Are you going to annotate
the declaration of strcpy() with the fact that it returns its first
argument?

And what about functions that don't return one of their arguments, but
just something whose lifetime is bound to it (like for example an
instance variable)? Are you going to introduce a general "lifetime of
x does not exceed lifetime of y" declaration syntax?

What if not raw pointers are used, but some variety of smart pointers?
How do you enable the compiler to infer the relative lifetime of their
pointees?

-- Niklas Matthies

Niklas Matthies

unread,
Apr 9, 2006, 4:52:44 AM4/9/06
to
On 2006-04-08 10:08, Andrei Alexandrescu (See Website For Email) wrote:
> Niklas Matthies wrote:
>> That doesn't scale at all. For example
>>
>> void f(T * auto ptr)
>> {
>> some_stl_algo(foo, boost::bind(bar, ptr));
>> }
>>
>> won't work because the 'bind' functor isn't allowed to store the auto
>> pointer. Same here:
>>
>> void f(Database * auto db)
>> {
>> db->connect();
>> ON_BLOCK_EXIT(db, &Database::disconnect);
>> perform_transaction(db);
>> }
>>
>> Or if you want to do
>>
>> void f(Database * auto db)
>> {
>> DBConnection conn(db);
>> perform_transaction(conn);
>> }
>>
>> how can 'conn' hold a reference to 'db'?
>
> The sound way to solve all of these issues is to propagate the
> "auto" qualifier to members, in analogy with const.

How will you enable the copying of the function object (involving
the copying of its auto pointer member) needed in the first example
above?

-- Niklas Matthies

Andrei Alexandrescu (See Website For Email)

unread,
Apr 10, 2006, 9:18:21 AM4/10/06
to
In-Reply-To: <slrne3fb4t.2bs...@nmhq.net>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Niklas Matthies wrote:
>>> char * auto foo(char * auto dst)
>>> {
>>> return strcpy(dst, "bla");
>>> }

> How are you going to make 'foo' above work? Are you going to annotate


> the declaration of strcpy() with the fact that it returns its first
> argument?

There is no need. A function that returns an *auto can only return
either one of its *auto parameters, a pointer to static storage, or NULL.

> just something whose lifetime is bound to it (like for example an
> instance variable)? Are you going to introduce a general "lifetime of
> x does not exceed lifetime of y" declaration syntax?

There is no need for that; the compiler can always infer that.

> What if not raw pointers are used, but some variety of smart pointers?
> How do you enable the compiler to infer the relative lifetime of their
> pointees?

An example would be helpful. In essence, I believe that problem is one
of those addressed by the propagation of the auto qualifier to members.


Andrei

Andrei Alexandrescu (See Website For Email)

unread,
Apr 10, 2006, 9:20:53 AM4/10/06
to
Niklas Matthies wrote:
> On 2006-04-08 10:08, Andrei Alexandrescu (See Website For Email) wrote:
>
>>Niklas Matthies wrote:
>>
>>>That doesn't scale at all. For example
>>>
>>> void f(T * auto ptr)
>>> {
>>> some_stl_algo(foo, boost::bind(bar, ptr));
>>> }
> How will you enable the copying of the function object (involving
> the copying of its auto pointer member) needed in the first example
> above?

The bind object stores its incoming argument in a member. In an
automatic object, it's sound to pass an *auto of larger scope as a
member initialized. The only thing is that the compiler must modularly
know that we're initializing an automatic bind object. So there must be
an auto qualifier upon constructor's declaration:

struct bind {
bind(T *auto p) auto
: p_(p)
{}
T* p;
};

The underlying principle is immutable: you _are_ allowed to use *auto to
initialize *auto of lesser scope. The only trick is to keep the compiler
informed.

kanze

unread,
Apr 11, 2006, 9:12:02 AM4/11/06
to
Mirek Fidler wrote:

[...]


> > With current C++, you have to indicate the absence of pointers
> > explicitly (and manually). If GC were standard, at least
> > according to the proposal before the committee, the compiler
> > could generate the necessary notation.

> Even with reinterpret_casts? ;) I still do not see how you
> could integrate non-conservative GC with C++ that would behave
> correctly with the current code...

There are some restrictions, which occasionnally result in
"pinning" some objects, i.e. doing conservative garbage
collection for some spaces. I'm not sure where
reinterpret_cast fits in there; the compiler does know about it,
and can inform the garbage collector. And of course, most of
the uses of reinterpret_cast are implementation dependant, and
need special handling anyway.

If you're concerned with what is legal (but not very often used)
today, then even conservative GC doesn't work. Part of the
reason for making GC part of the language is to enable more of
these technologies. While permitting a module to be marked as
not supporting garbage collection.

It won't be easy to integrate all of the existing code into a
C++ with garbage collections. Any more than it was easy to
integrate existing template code into compilers with two-phased
look-up, or non-exception safe code into a system with
exceptions. Such is the price of progress. Unlike the other
two examples above, the standard itself provides for a migration
path. And the problem is certainly an order of magnitude
simpler than the introduction of exceptions.

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

kanze

unread,
Apr 11, 2006, 9:12:49 AM4/11/06
to
Martin Aupperle wrote:
> >I wanted to make the point that all of these very popular GC
> >languages have either largely ignored the problem of
> >deterministic disposal of resources or limited the ways in
> >which one can use such an object.

> Worse: They not only have ignored it, many C# (and I guess
> Java too) programmers simply are not aware of the problem. I
> many times heard arguments like "this is old C++ thinking! We
> don't need deterministic finalization because the GC cleans
> up!". Unbelievable? It's true.

That, regrettable, is true. (At least for Java programmers --
I've no experience with C#; maybe Herb is doing a better job at
training them.) Far too often, I've heard comments to the
effect that "memory leaks are impossible in Java". Still, such
people aren't going to write working programs in any language,
and they probably won't return to C++, since C++ has passed the
stage of being the latest in fad. So their existance shouldn't
be used as an argument to refuse essential tools to responsible
programmers. If you eliminate everything that can be misused
from C++, there won't be much left.

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

It is loading more messages.
0 new messages