Re: If GC is the solution, then what is the problem?
charleyb123@gmail.com wrote:
kanze wrote:
charleyb123@gmail.com wrote:
Walter Bright spaketh:
[...]
C++ should have acquired GC about 15 years ago.
Gene Bushuyev replied:
<snip, > And the reason that there is no GC neither in the
C++ Standard nor as a typical extension is the lack of
demand. Good C++ practices tend to produce the objects
with automatic storage duration. Resourse management is
done in ctor/dtor, which is robust, flexible and
deterministic.
THANK YOU, Gene.
For the false illusion? There IS a large demand for garbage
collection in C++. The standards committee is seriously
considering it for the next version of the standard. Third
party companies are successfully selling garbage collection
as an add in, and an open source implementation is widely
used. <,snip>
They can consider it all they want. ;-) I was just happy to
hear a dissenting view (GC isn't universally desired in C++).
The problem is that the dissenting view comes uniquely from
people who don't know garbage collection, and consists either of
vacuous statements that don't really mean anything, or of
complaints about things that aren't problems, and that shows
their lack of knowledge on the subject. If you take Gene's
statements:
-- There is a demand, a very strong demand. The people working
on the issue in the C++ standards committee are doing so
because there is a demand. The people in the committee who
voted in favor of it also did so because there is a demand.
-- Good C++ practices does include using automatic objects as
much as possible. I don't think anyone would dispute that.
But what does that have to do with garbage collection?
-- Resource management, in general is done in the destructor.
Memory happens to be a very special resource, however, for
which a good alternative exists. Why write code when you
don't need to?
I bite my tongue every time GC comes up. <snip, has
utility in other languages but not C++>,
I would *never* use GC [...in C++]
That's an interesting statement, because compile-time static
typing for dynamically allocated objects requires garbage
collection. It can't be done otherwise, or at least, I
don't think so. C++ implementations don't do it; they use
the "undefined behavior" to let them off the hook.
My assertion is that the stronger the type, and the more
mature the design, the more deliberate you want to be in
controlling your object lifecycle (and not leave anything to
an external system, which GC is, because GC doesn't have your
model dependencies and business logic).
Your assertion doesn't hold water. Strong typechecking of
dynamically allocated objects requires garbage collecction.
Strong typechecking means that if I have a T*, it is either
null, or points to an object of type T (or derived from type
T---but polymorphism is actually a contradiction with strong
static typechecking). If the object to which a pointer points
can cease to exist while the pointer still exists, than you
don't have strong typechecking.
Perfectly strong typechecking probably isn't desirable. Or
rather, the cost---forbidding pointers to local objects---is
probably higher than the gains you'd get for it. There's also
the fact that garbage collection can't prevent objects from
logically ceasing to exist, even though pointers to them exist.
The best you can do is dynamic checking; garbage collection does
ensure that the memory underlying the object doesn't get
recycled as long as a pointer to it exists, so you can add flags
and runtime checks to detect the error.
IMHO, for most OO, it's simply a bad way to view the problem.
For the *vast* majority of our designs, object ownership is
defined through well-understood containment within
well-defined (logical) abstractions.
A large majority, yes. And there are certainly objects for
which garbage collection is not really the right solution
(although even with such objects, it permits some form of
type safety, which isn't possible otherwise). I have, in
fact, often wished for a sort of reverse garbage collection
as well: rather than deleting an object when there are no
more pointers to it, it would get rid of all pointers to an
object when it the object is deleted.
What you're calling GC and "reverse" GC, I'm suggesting is
better handled with business logic as defined through your
model (since it actually knows what all your types mean
anyway).
Reverse GC must be handled through business logic, because there
is no alternative. It usually involves not a few lines of code,
which have to be written and maintained. GC can be successfully
handled through business logic. It also involves additional
lines of code, which have to be written and maintained. When
there exists a perfectly working alternative, it would be
foolish not to use it. (And unprofessional: my customers don't
pay me to write unnecessary lines of code; they pay me to
produce solutions, as efficiently as possible.)
The fact that it isn't necessary all of the time doesn't
mean that it isn't useful in enough cases to be worthwhile.
I use GC all the type in Perl. I go decades without it in C++.
I concede the point that if that's how you view design, GC is
a valid computer science artifact to legitimately address some
problems in some domains. (I'd just prefer it to be in a
library external to the C++ standard itself.)
I can understand that. The problem is that it can be done much
more efficient if the compiler collaborates. The other argument
in favor of a language solution is that it will also be possible
to declare, at the language level, that some code is
incompatible with garbage collection. Which is an important
point as well: while there is close to a consensus that adding
garbage collection would improve C++, there is also a very
strong consensus that it must remain possible to write C++
programs without it.
If it's not, IMHO, you are missing key abstractions.
It depends on the object. Many objects DO have explicit
lifetimes. All garbage collection brings to them is an
ability to detect the errors: an explicit and understandable
error message, instead of undefined behavior. Many others
however, don't really need an explicit lifetime, as long as
they are there when needed (i.e. someone holds a pointer to
them). For those, garbage collection is THE solution. (And
of course, a lot of objects have value semantics, and should
probably never be allocated dynamically anyway. For those,
of course, garbage collection is irrelevant.)
You're describing a case where I agree in some GC utility:
When many "trivial" non-connected objects are popping in and
out, all over the system. That's how Perl/Python work too,
and GC is quite handy there.
I don't commonly find that design in most C++ systems (the
types are stronger, and they have better "knowledge" of whom
they reference since that's the business logic).
I certainly agree that not everything should be garbage
collected. My value objects are still pretty much always on the
stack, as are my RAII objects. My business entity objects also
continue to have explicit lifetimes, although I count on garbage
collection to recover the memory. (It saves a few lines of
code, but nothing dramatic.) But there remain enough other
objects (maybe 10 or 20%) for which garbage collection is a
significant gain. And one or two places where the alternatives
are really awkward.
<snip>,
All GC does is say, "I create objects but don't feel like
defining an owner, so I just leave my mess for the janitor,
whom I assume will clean up for me in a proper way."
It's not a question of feeling, but of design. There are
objects for which artificially designating an owner is just
extra work, and is, in fact, an artifact of a weakness in the
language.
The original statement suggests the janitor doesn't have
sufficient context to make decisions about what should be
cleaned up, when, how, and in what order.
Actual experience shows that he does.
Yes, I concede the point that GC can work well for the
"trivial" case where the object isn't coupled to anything and
no other specifal considerations exist.
Unfortunately, I find that small (normal) changes to a design
results in your system now having "non-trivial" cleanup
considerations that GC can't handle. In that case, I find
that rather than getting GC to "behave properly", it would
have been faster/easier/more robust/more correct to simply
address object lifecycles in my design.
I'd be *so sad* if the C++ standard got screwed up with GC,
and I had to figure out how to work around it and shut it
off.
If you don't like being more productive, that's
understandable. If you're paid by the line, garbage
collection will certainly reduce your income.
Now, now, be nice. ;-) You're a smart guy that raises valid
points, so I'm merely attempting to respond honestly.
I appreciate technical arguments. But in the past, we've heard
garbage collection opponents bringing up arguments that it was
only laziness, etc. And it's very hard to respond to arguments
which are completely irrelevant (and often honestly made, simply
because the person in question doesn't really know what garbage
collection is, or how it is used). A statement like "the
standard got screwed up with GC" is loaded. It isn't a
technical argument, but rather presupposes the premise. The C++
standard will not be "screwed up" by garbage collection, and
believe it or not, the people working hardest to add it to the
standard do take into account that there are also times that it
isn't appropriate.
But, my original comment was true: I'd be sad if GC were
added to C++, and I'd try to find a way to shut it off,
because I don't have use for it (even considering my honest
goal for productivity ;-).
Well, prepare to be sad. And although it shouldn't be difficult
to turn off, I'd suggest that you leave it on. Anywhere objects
have a determistic lifetime, they continue to have one. But
there are (and will continue to be) objects which are just gobs
of data, or just agents, whose lifetime is irrelevant to the
application. If such an object is owned and used by just one
client, you'll save maybe one line in the destructor; you might
save a little in the class definition as well, because you won't
have to think about what type of pointer to use to ensure
exception safety. If the object is effectively used by several
clients, on the other hand, you'll save a significant amount of
work by letting garbage collection take care of it.
This obviously doesn't apply to all objects. You still have to
analyse what the lifetime should be. The only difference is
that with garbage collection, when the anaysis shows that no
particular lifetime management is necessary, you're work is
done; without garbage collection, you still have to be concerned
with the memory management issue down to the lowest coding
levels. And that's extra work. It's more lines of code to
write and to maintain.
--
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]