SGCL - Garbage Collector for C++

I

Ian Collins

James said:
Maybe because he knows what the object is used for, and why he
created it in the first place?

But he'd have to whether the object had to be deleted, or could be left
for the GC.
Not an irrelevance. Less important, but programmer productivity
is never really irrelevant.
I still contend that correct and systematic use of smart pointers does
make GC an irrelevance without any sacrifice in productivity.
I tried that, and gave up with it. It resulted in too many
memory leaks. In my applications, most pointers are used for
navigation, not for ownership. And raw pointers work perfectly
well for navigation.
Ah, well that's where our domains differ. Most of the places where I
would have used pointers are in containers, manipulating DOM trees or
for passing objects between threads. Moving to smart pointers made life
so much easier.
 
J

Juha Nieminen

James said:
Yes. In a lot of applications, garbage collection is faster,
but typically, it uses more memory. Given the size of current
memories, this usually isn't an issue (but it could be in some
applications, particularly numeric simulations of large scale
physical phenomena, like weather).

There are other less-understood problems with garbage collection which
few people realize.

One such problem is that garbage collection can be quite detrimental
with respect to swapping.

Typically if a program allocates fair amounts of memory, but is
otherwise designed to simply sit idly on the background most of the time
and run from time to time to make some light tasks (such as many device
managers and such in Windows do), the majority of their unused allocated
memory will be swapped to disk, especially if other applications request
that memory. If the tasks this program is asked to perform never read
the swapped blocks, they will stay in the swap.

However, if the program in question uses GC, and the GC engine happens
to be triggered at some point, it will scan all the memory blocks the
program is using. Naturally if these memory blocks were in the swap,
they will be swapped to memory from there. If there was nothing to
garbage-collect, this swapping-out was a completely useless waste of
resources.

This can become extremely detrimental if the system was running very
low on memory to begin with. If an inappropriate GC engine happens to be
triggered at the wrong time, it can cause unnecessary swapping where
none would have been needed, disrupting the major task the system was
performing at that moment.

"Those device apps don't use GC." Oh, but they do. They do. GC is the
current trend, and they follow it.
 
J

jason.cipriani

[snip]
There are other less-understood problems with garbage collection which
few people realize.

One such problem is that garbage collection can be quite detrimental
with respect to swapping.
[snip]

I can speak for this; this was especially a problem on Apple's JVM, at
least as of about a year ago, I'm not sure if they've fixed the issues
since. In particular, there was a rather memory-intensive, popular
online game that stored most of it's graphics in system memory, and
when it decided to run the GC it would have to swap in all the pages
-- and it crippled the *entire* system for 30-45 seconds every 10
minutes or so. It was very unacceptable, and made the game virtually
unplayable for nearly all of the Mac users who were trying to play it.

It was a problem that did not happen on non-Apple JVM's. I think the
major problem there was Apple's algorithm for deciding when to run the
garbage collector -- it seemed to only run it when the system was
running low on memory, waiting until the last minute. Unfortunately,
this also meant most of the "garbage" was probably in the page file.
If it had run the garbage collector more frequently, perhaps at
regular intervals, I do not think that issue would have occurred.

Still, in that case, it seemed like more of a specific GC
implementation issue rather than a problem with garbage collection
itself. The problem was unique to Apple's JVM.

Just thought I'd share the memory of that game,
Jason
 
P

peter koch

But he'd have to whether the object had to be deleted, or could be left
for the GC.

That is a theoretical problem, yes. For an encapsulated object you
might not know if it has any real resources. Worse is that you might
have a base object and have no idea as to what happens in the
subobject.
In practice it might not be a real problem. I could easily imagine
problematic cases, but this is not a big problem and could be solved
by e.g. documenting the base class as e.g. "you are not allowed to
obtain any resources here".
The biggest problem is with template programming. My guess is that
programming on this abstraction-level will often require an extra
level of support or some exttra careful programming.

[snip]
Ah, well that's where our domains differ.  Most of the places where I
would have used pointers are in containers, manipulating DOM trees or
for passing objects between threads.  Moving to smart pointers made life
so much easier.

I have the same experience as you: it would never have been a major
convenience for me to have a garbage collector, but I've had great use
for smart pointers.

/Peter
 
J

James Kanze

Don't take my word for it.

# The Java run-time system takes advantage of these idle periods and runs
# the garbage collector in a low priority thread when no other threads are
# competing for CPU cycles.

In addition to running it when there is no memory available for
a new. That's a simple (and frequently applied) optimization
measure, but it doesn't change the fact that if your application
doesn't leak memory, and doesn't require more than the available
memory, it will not crash because of a lack of memory. In other
words, the scenario that you described isn't possible.
 
J

James Kanze

But he'd have to whether the object had to be deleted, or
could be left for the GC.

Certainly. But that's always the case. You don't create
objects without knowing the role of the object, or what it's
there for.
I still contend that correct and systematic use of smart pointers does
make GC an irrelevance without any sacrifice in productivity.

It adds to the programmer work load. It's more code you have to
write.
Ah, well that's where our domains differ. Most of the places where I
would have used pointers are in containers, manipulating DOM trees or
for passing objects between threads.

I don't know what a DOM tree is, but I certainly keep pointers
in containers, and I do pass them between threads. Passing them
between threads is one case where I do use a smart
pointer---std::auto_ptr---because once I've handed the object
off, I don't want to be able to access it again in the
originating thread. (The objects passed between threads are
almost always "agents".)

Most of my entity objects are related to other objects, and
contain pointers to these other objects. Raw pointers, since no
ownership is involved. And most of my containers are also used
for navigation---either a 1 to n relationship, or for lookup
(finding the object from an external name). Again, raw pointers
fill the bill perfectly.
Moving to smart pointers made life so much easier.

If you don't have garbage collection, smart pointers may be
better than nothing. In some cases. I use all three: raw
pointers (for pure navigation), garbage collection (for memory
management) and smart pointers (for special cases like passing
between threads, or associating a lock with a pointer). If for
some reason I can't use garbage collection, then I'll also use
smart pointers to simulate it. But that requires some
additional effort.
 
J

James Kanze

My point exactly. You're arguing for the sake of arguing.

No. You said that they were more or less one and the same
thing. They aren't, at least not in C++. They are basically
two distinct operations, which are in once special case invoked
by the same expression.
Irrelevant. Whether or not they are separate concepts reflects
nothing on the fact that separating their respective
occurences buys you nothing, or makes any sense.

Which doubtlessly explains why in C++ they are completely
separated into two separate functions, why in the STL (and every
other library of containers I've used) they are separate.

The fact remains that they are two separate concepts, and
combining to concerns in one action is never a good thing. It's
a violation of basic good design principles.
Not the ones that rely on garbage collection.

Where do you get that idea? In the Java projects I've worked
on, we've always considered object lifetime issues.
After all, if they did undertand the concept, they would
understand when their objects' lifetime has expired, and they
can be destroyed and their memory gets reclaimed.

Certainly. Anyone who can write correct code with garbage
collection can write it without, just as anyone who cannot write
correct code without garbage collection can't write it with.
That's never been in doubt. The difference is simply that if
you do know how to write correct code, it requires less work to
do so with garbage collection.
You seem to be carrying a misunderstanding that just because
an explicit class destructor is not required, it must mean
that the class destructor does not exist.
That, of course, is wrong. The class may, for example, contain
member objects that themselves have an explicit destructor.
Therefore, even if you do not need to code an explicit
destructor, it still, heavens-to-Betsy, exists. For the
obvious reasons.

You seem to be carrying a misunderstanding that people write
code at random, without doing any proper design first. And that
people will take an interface designed to fulfil one role in the
application, and use it to do something completely different.
Such techniques don't work. Garbage collection or not.
So you really can't just wash your hands of the whole matter,
by the virtue of claiming that you do not need to write a
destructor for your class. That's because there's always a
destructor, for every class. Just because you do not have to
explicitly define one, does not mean that the class destructor
does not exist. This does not excuse you from the
resposibility of properly implementing your object's lifetime,
and instead foisting it off on some sloppy garbage collector.

You don't seem to understand that good code is designed. It
doesn't just happen. (And again, garbage collection changes
nothing at that level.)
Generic garbage collection in the C++ context never takes form
of "well, you explicitly invoke the destructor when you
should, and I'll take care of releasing the memory at some
point later down the line".

Exactly. You invoke the destructor IF the object has
significant behavior which must be done at the end of its
lifetime. Otherwise, you don't bother. There are whole classes
of object types which by definition won't have significant
behavior which must be done at the end of their lifetime. There
are even object types which don't really have a defined
lifetime. And whether you invoke the destructor or not,
sometime later, WHEN no one else can access the object, the
memory it occupies will be reclaimed.

And that's a very big WHEN, because just because you've
destructed the object doesn't mean that no one else will access
it. With garbage collection, of course, you can verify that no
one does, and cause an assertion failure if they try to.
Without garbage collection, the memory may have been recycled,
and it's anyone's guess.
It's always "well, don't worry about the objects, when I
figure out they're no longer needed, I'll destroy them and
reclaim their memory".

Why do you keep repeating this, when it's been explained that it
is false. Garbage collection doesn't destruct anything, it just
reclaims memory which is otherwise inaccessible.
Brilliant. And when you figure out that no such pointers
exists, you're going to finally kiss it good-bye, right?

When no such pointers exist, no one can incorrecly access the no
longer existing object. So it no longer matters if the memory
image is there or not.
It's amazing how better this approach is, rather than just
using shared_ptr (or a better implemented alternative). Why
have to use such a bland concept like shared_ptr, when you can
use this wonderfully-convoluted object model?

Because shared_ptr doesn't work, and garbage collection does?
You certainly need a lot less code to write if you disclaim
the responsibility of properly tracking the objects' lifetime,
and foisting it off on some garbage collection algorithm.

It would help discussion if you'd at least try to be a little
bit honest. It's now been explained I don't know how many times
that garbage collection has nothing to do with object lifetime.
Except that it does allow detection of the error of accidentally
trying to access an object which no longer exists.
I would not call that "robust", by any stretch of imagination.

You call random (undefined) behavior more robust than detecting
programming errors?
Here's another hair to split, for you: _____________________

I'm not splitting hairs. The problem is that you just don't
seem to understand the basic C++ object mode, and the role
garbage collection plays in it.
Of course it's a tool. It's a tool for those who are too lazy,
or incompetent, to properly design their classes, and track
their instances' lifetime.

It's a tool for those who are too professional to artificially
create unnecessary work, just so that they can bill extra hours.
It's a tool for those who insist on robust software, with
serious error detection.
Your definition of "professional" does not seem to be the same
one as mine's.

I haven't figured yours out yet. Mine is simple: I develop
reliable and maintainable software, at the lowest possible cost
to my customer. Not using tools that effectively reduce my
workload and increase the reliability of the software would be
unprofessional, or even dishonest.
If I see someone's spaghetti code missing the obvious deletes,
in the appropriate places, I ask them about it, and they say
"oh, don't worry about, the garbage collector will take care
of it", I would not describe such a person as a
"professional".

In other words, the more deletes, the more professional.
Strange definition, to say the least.
 
I

Ian Collins

James said:
Certainly. But that's always the case. You don't create
objects without knowing the role of the object, or what it's
there for.
But why add yet another facet?
It adds to the programmer work load. It's more code you have to
write.
No, once written, smart pointer types can be used just like any other,
no extra work at all. One may have to choose which type to use and
there is always the risk of getting it wrong. But the same could happen
with a mix of GC and user managed objects.

As I said before, it's not GC I object to, it's mixing GC and
"conventional" memory management. I'd also object the mixing raw
pointers with smart pointers for dynamic objects.
I don't know what a DOM tree is

The Document Object Model. I do a lot of work with XML and XHTML documents!
 
J

James Kanze

It's already apparent that you don't really understand the
problems with garbage collection,

Until now, it's been you whose shown an absense of
understanding---of garbage collection, of program design, of the
C++ object model. I'm beginning to wonder what you do
understand.
as it gets clearly demonstrated the Java model,

Java is not C++, and it uses different paradigms. Garbage
collection is essential in Java, because all objects must be
allocated dynamically, and user defined types can't have value
semantics. It's optional in C++, because we do have value
semantics. Optional, but it still saves the programmer some
unnecessary work.
and why it forces you to explicitly code exception handling,
when dealing with external resources,

The reason you need explict try/catch or try/finally blocks in
Java is because that's Java's model. In C++, you use
destructors.

Garbage collection has absolutely nothing to do with it. The
absense of on stack objects and destructors is the key
difference here.
thus defeating the very thing that's touted as Java's
advantage of not forcing the programmer to manage the object's
lifetimes, and letting the VM take care of it.

Some advertising writers may claim that, but no professional
programmer, regardless of the language he uses, would pretend
that you can ignore object lifetimes. The authors of the Java
standard library certainly didn't.
I'll spell it out, but just once. You're constructing a java
object that contains a java.io.File, as one of its members (or
any other object that refers to some external resource). Right
after you acquire the external resource (by opening the file,
or an equivalent operation on another type of a resource), you
must immediately have a try/catch block that will release the
external resource if an exception occurs before the object
gets completely constructed. Because if one occurs and you
don't catch it, then, due to the wonders of the Java VM, that
java.io.File object will still exist and claim the external
resource, until the VM decides to GC it. So, lather, rinse,
repeat, and you're out of file descriptors, since the VM
thinks it still has plenty of memory, and it doesn't bother to
finalize and collect all the java.io.File objects that are
littering the heap.

And why? That's not because of garbage collection---the
situation would be exactly the same if you created an ofstream
dynamically, instead of making it a member. The reason is
because Java doesn't have destructors, nor true member
subobjects.

(Of course, files are a special case, because you wouldn't
normally close them in a destructor anyway.)
And you now have to percolate and code the same clumsy
exception handling all the way up your class hierarchy, and
with anything else that touches any part of this class
hierarchy. Your homework assignment is to figure out why.
There you go, the wonderful advantages of garbage collection,
for you.

The problem with all of your arguments is that they have
absolutely nothing to do with garbage collection.
WHOOOOOOOOOOOOSH!!! Right over your head, again.

Why is it that whenever I bring up an irrefutable point (e.g.
the necessity of checking the status after close), you go off
the edge?
 
I

Ioannis Vranos

James said:
Yes. I wasn't disagreeing with you. Just trying to say it in
an even stronger way.


Leaving "Java" apart, which is a close language syntax + virtual machine
combination, you may check this regarding C++/CLI:

http://en.wikipedia.org/wiki/C++/CLI


The managed class ("ref class") comes with both a deterministic
destructor and a non-deterministic destructor (called by the GC). If you
the managed object reaches the end of its scope (the managed objects can
be like regular objects and not required to be allocated by gcnew), or
you delete them explicitly if you have created them with gcnew, the
deterministic destructor is called. If you have allocated the managed
object with gcnew and you leave it to be garbage collected, the
non-deterministic destructor is called. I think this is a very good
approach. At the same time, ISO C++ code can be used stand-alone or
mixed with managed code.


Even at the time I was creating .NET applications with "C++ managed
extensions" where every managed object had to be allocated with __gcnew
and left to be destroyed by the GC, while you could define an explicit
function to call so as to free allocated resources explicitly when you
wanted, and not wait for GC to free the resources by calling the
Finalizer (the non-deterministic destructor that was the only kind of
destructor for managed classes), leaving all those Forms, Buttons etc to
the GC was a great relief, not having to worry about explicitly
releasing all those stuff. So I think in normal PC GUI
applications,garbage collection has a place to make the programmer's
life easier, where space efficiency is not a primary concern (that is
for the usual user applications).


I remember some company or MS had ported Quake II to .NET and the
runt-time cost was only about 10%. So even Quake II where speed is a
primary concern, the GC didn't cause much trouble, but rather it helped
much.


GC has a place in the present and in the future, I think all must come
in terms with that. We can't stick in the past, technology is moving
forward. If you like it, use it, if you don't like it, don't use it.
 
I

Ioannis Vranos

Ioannis said:
Leaving "Java" apart, which is a close language syntax + virtual machine
combination, you may check this regarding C++/CLI:

http://en.wikipedia.org/wiki/C++/CLI


The managed class ("ref class") comes with both a deterministic
destructor and a non-deterministic destructor (called by the GC). If you
the managed object reaches the end of its scope (the managed objects can
be like regular objects and not required to be allocated by gcnew), or
you delete them explicitly if you have created them with gcnew, the
deterministic destructor is called. If you have allocated the managed
object with gcnew and you leave it to be garbage collected, the
non-deterministic destructor is called. I think this is a very good
approach. At the same time, ISO C++ code can be used stand-alone or
mixed with managed code.


Even at the time I was creating .NET applications with "C++ managed
extensions" where every managed object had to be allocated with __gcnew
and left to be destroyed by the GC, while you could define an explicit
function to call so as to free allocated resources explicitly when you
wanted, and not wait for GC to free the resources by calling the
Finalizer (the non-deterministic destructor that was the only kind of
destructor for managed classes), leaving all those Forms, Buttons etc to
the GC was a great relief, not having to worry about explicitly
releasing all those stuff. So I think in normal PC GUI
applications,garbage collection has a place to make the programmer's
life easier, where space efficiency is not a primary concern (that is
for the usual user applications).


I remember some company or MS had ported Quake II to .NET and the
runt-time cost was only about 10%. So even Quake II where speed is a
primary concern, the GC didn't cause much trouble, but rather it helped
much.


GC has a place in the present and in the future, I think all must come
in terms with that. We can't stick in the past, technology is moving
forward. If you like it, use it, if you don't like it, don't use it.


The C++/CLI standard can be found here:

http://www.ecma-international.org/publications/standards/Ecma-372.htm
 
S

Sam

James said:
No. You said that they were more or less one and the same
thing. They aren't, at least not in C++.

Here's another hair for you to split: ______________________________
They are basically
two distinct operations, which are in once special case invoked
by the same expression.

Anyone who is not involved with splitting hairs, for a living, would clearly
understand that I was referring to the fact that "delete" does both:
destruction and memory reclamation. It's one shot, in C++.
Which doubtlessly explains why in C++ they are completely
separated into two separate functions,

Damn right! There's no such thing as "delete", in C++, which handles both
object destruction and memory release. There's a "foo", that does the first
part, and "bar", that does the second one. My mistake.
Why do you keep repeating this, when it's been explained that it
is false. Garbage collection doesn't destruct anything, it just
reclaims memory which is otherwise inaccessible.

Why do you keep repeating this, that object destruction and memory release
are two completely separate processes in C++, when it's been explained to
you that it's completely false. Maybe on your planet C++ works this way, but
not on this one.
When no such pointers exist, no one can incorrecly access the no
longer existing object. So it no longer matters if the memory
image is there or not.

And how do you expect to arrive to such a conclusion? A random number
generator? Yippee! It evaluated to 0.53 -- must mean that no further
pointers remain, and we can reclaim the object.
Because shared_ptr doesn't work, and garbage collection does?

Not on my planet, where it works every time it's used properly, and garbage
collection is an ugly hack for the lazy asses who can't be bothered to track
and manage their objects, properly.
It would help discussion if you'd at least try to be a little
bit honest. It's now been explained I don't know how many times
that garbage collection has nothing to do with object lifetime.

Repeating the same absurdity a given number of times won't suddenly turn it
into sense. The whole and the only purpose of garbage collection is to clean
up after yourself, when you can't be bothered to do it properly. That's the
sole and the only purpose for it, because if you do know what you're doing,
you simply don't need garbage collection. Not in C++, at least.
Except that it does allow detection of the error of accidentally
trying to access an object which no longer exists.

Brilliant! "I'm too stupid to know how to track my objects' lifetime, so
I'll just use garbage collection in some twisted way, in order to save my
lazy ass."

You call random (undefined) behavior more robust than detecting
programming errors?

I call "knowing how to do your job, WRT class design an implementation" more
robust than using an ugly, revolting hack like C++-based garbage collection.
I'm not splitting hairs. The problem is that you just don't
seem to understand the basic C++ object mode, and the role
garbage collection plays in it.

There's no such thing as garbage collection in "basic C++ object mode." The
formal language just does not define anything of that sort. Feel free to
cite the part of ISO/IEC 14882:2003 that defines garbage collection for
"basic C++ object mode". Whatever that is.

Garbage collection for C++ always involves some third-party slapdash code
that seems to compete with Boost for the gold prize in the C++ obfuscation
context.

Actually, reflecting on the last 10+ years of looking at C++ code in
financial apps -- that are responsible for moving huge volumes of business
critical market data -- I do not recall even a single instance of anyone
using anything can even be remotely described, in some nightmarish context,
as "garbage collection." Sorry, but established facts disagree with your
theories.
It's a tool for those who are too professional to artificially
create unnecessary work, just so that they can bill extra hours.

"C++ garbage collection" is the very essence of "unnecessary work".
It's a tool for those who insist on robust software, with
serious error detection.

You better sit down, because the following may come as a shock to you.

Sitting down? Ok.

Here's a newsflash: there's plenty of "robust software" going around that
does not involve garbage collection. Well, how'd that happen, huh?
I haven't figured yours out yet. Mine is simple: I develop
reliable and maintainable software, at the lowest possible cost
to my customer. Not using tools that effectively reduce my
workload and increase the reliability of the software would be
unprofessional, or even dishonest.

That's your opinion. If I ever meet some candidate who walks off the street,
and starts spouting something or other about the wonders of garbage
collection in C++, I'll politely thank him, strike his name off the list,
and move on to the next one. Nobody who knows what he's doing, in C++, has
any use for this garbage collection nonsense.

See -- I prefer to use "tools" and "approaches" that eliminate even the
possibility of memory corruption, using some basic and simple programming
practices. Or at least most of it, instead of slapping together some
spaghetti code together, and rely on some convoluted version of garbage
collection to help me debug my code and track down any errors in object
usage.

It's really not that difficult, and is the very essence of "lowest" possible
cost in terms of development and debugging.
In other words, the more deletes, the more professional.
Strange definition, to say the least.

Where did you imagine the word "more"?



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHy3xRx9p3GYHlUOIRAovnAJ0c0j+U0LvnA0NeaSsvPwjuhLnSRQCfdTng
Gow4rjmwM+D6YNHVf+fLV8E=
=7Vs2
-----END PGP SIGNATURE-----
 
S

Sam

James said:
Until now, it's been you whose shown an absense of
understanding---of garbage collection, of program design, of the
C++ object model. I'm beginning to wonder what you do
understand.

There is no garbage collection in the "C++ object model", and yes, I plead
guilty to failing to understand completely the incompetence and lack of
experience that would require someone to resort to such an ugly hack in
order to accomplish anything of significance.
Java is not C++, and it uses different paradigms. Garbage

Bingo! So, if you want garbage collection, go have fun in Java.
collection is essential in Java, because all objects must be
allocated dynamically, and user defined types can't have value
semantics. It's optional in C++, because we do have value
semantics. Optional, but it still saves the programmer some
unnecessary work.

No, it's not "optional" in C++. It does not exist, at all, in C++. Go look
up the "optional" part of ISO/IEC 14882:2003 that defines whatever you think
"garbage collection" means in the C++ context. I eagerly await the results
of your search.
The reason you need explict try/catch or try/finally blocks in
Java is because that's Java's model. In C++, you use
destructors.

No, you just know even less about Java that you know about C++.
Garbage collection has absolutely nothing to do with it. The
absense of on stack objects and destructors is the key
difference here.

It has everything to do with the garbage collection aspect of Java, and its
impact on external resources.
Some advertising writers may claim that, but no professional
programmer, regardless of the language he uses, would pretend
that you can ignore object lifetimes.

You just admitted, in another message, that "professional" programmers
welcome the opportunity to ignore object lifetimes, just so they can deliver
a product at a "lowest" cost.

Which one is it?
And why? That's not because of garbage collection---the

It's precisely because of garbage collection. If Java did not use garbage
collection, and finalized and released objects immediately after they went
out of scope, this problem would not exist. Here's some paper and pencil, go
and work it out for yourself.

Sorry to have to confuse you with facts.
situation would be exactly the same if you created an ofstream
dynamically, instead of making it a member. The reason is
because Java doesn't have destructors, nor true member
subobjects.

Java certain has destructors. Just because you don't know about them,
doesn't mean that they do not exist.
(Of course, files are a special case, because you wouldn't
normally close them in a destructor anyway.)

Brilliant!

Listen up folks! You're about to learn something, here! Don't bother to
close those pesky files, in the destructors of objects which own them. Those
files will close by themselves, magically!

You learn something new every day, around here.
The problem with all of your arguments is that they have
absolutely nothing to do with garbage collection.

That straw you're grasping can't last much longer. Not only you're wrong WRT
garbage collection, you don't even fully understand what it means.



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHy3zJx9p3GYHlUOIRAhPVAJ9EKf+EFHcu6JhIY73yhNNaifNt1wCbBoX4
KPAe5mCX8HD8IuK1NneApdo=
=s6nx
-----END PGP SIGNATURE-----
 
I

Ian Collins

Sam said:
Damn right! There's no such thing as "delete", in C++, which handles
both object destruction and memory release. There's a "foo", that does
the first part, and "bar", that does the second one. My mistake.
Cool down chaps, you are arguing at cross purposes.

I may be completely wrong, but I think James was saying that with
containers (as typified by the STL) of pointers, destroying the
container does not free the memory associated with the pointers. If
(and this may be a big if) the referenced objects have trivial
destructors, garbage collection will mop them up.

No one would dispute deleting an object invokes its destructor and
releases the memory used by the object.

Now I would argue that smart pointers achieve the same result as GC in
that case. I would also argue that smart pointers work equally well
with objects with trivial destructors and objects with non-trivial
destructors, which makes them a better general purpose solution.

I would also go so far as to argue that smart pointers are more
idiomatic C++ than garbage collection. After all, the current standard
provides one (all be it unsuitable for use in containers, I never did
understand that decision) and the next will proved more versatile smart
pointers which are suitable for insertion into standard containers. We
will then have even less reason to use garbage collection with standard
containers.
 
K

Kai-Uwe Bux

Sam said:
James Kanze writes: [snip]
Garbage [snip]
collection is essential in Java, because all objects must be
allocated dynamically, and user defined types can't have value
semantics. It's optional in C++, because we do have value
semantics. Optional, but it still saves the programmer some
unnecessary work.

No, it's not "optional" in C++. It does not exist, at all, in C++. Go look
up the "optional" part of ISO/IEC 14882:2003 that defines whatever you
think "garbage collection" means in the C++ context. I eagerly await the
results of your search.

I don't think that is entirely correct. The C++ standard is worded very
cautiously with regard to new and delete to leave a tremendous amount of
freedom to the implementation. I think, a compliant implementation could
use garbage collection. In particular, I do not know of any language in the
C++ standard that would require the following program to ask the execution
environment for an unbounded amount of memory:

int main ( void ) {
while ( true ) {
new int ( 5 );
}
}


Best

Kai-Uwe Bux
 
C

Chris Thomasson

[...]
I don't know what a DOM tree is, but I certainly keep pointers
in containers, and I do pass them between threads. Passing them
between threads is one case where I do use a smart
pointer---std::auto_ptr---because once I've handed the object
off, I don't want to be able to access it again in the
originating thread. (The objects passed between threads are
almost always "agents".)

Yeah. You could do a very nice auto_ptr with the XCHG or SWAP/membar (e.g.,
x86/SPARC) instruction(s).

[...]
If you don't have garbage collection, smart pointers may be
better than nothing. In some cases. I use all three: raw
pointers (for pure navigation), garbage collection (for memory
management) and smart pointers (for special cases like passing
between threads, or associating a lock with a pointer). If for
some reason I can't use garbage collection, then I'll also use
smart pointers to simulate it. But that requires some
additional effort.

I prefer using a proxy garbage collector. One reason is because I can use
existing C malloc/free API implementations, and have the ability to define
garbage collected regions. Why would I want to use a traditional GC when I
could make clever use of RCU? You can read and ask questions about proxy GC
on 'comp.programming.threads'.
 
J

James Kanze

James Kanze wrote:
Leaving "Java" apart, which is a close language syntax +
virtual machine combination, you may check this regarding
C++/CLI:

The managed class ("ref class") comes with both a
deterministic destructor and a non-deterministic destructor
(called by the GC). If you the managed object reaches the end
of its scope (the managed objects can be like regular objects
and not required to be allocated by gcnew), or you delete them
explicitly if you have created them with gcnew, the
deterministic destructor is called. If you have allocated the
managed object with gcnew and you leave it to be garbage
collected, the non-deterministic destructor is called. I think
this is a very good approach. At the same time, ISO C++ code
can be used stand-alone or mixed with managed code.

There are too many "destructors" floating around there to please
me. When discussing such issues, I prefer to use distinct
names: dispose or destruct terminates the lifetime of the
object---regardless of how or where it was allocated, and
finalize is a function which is called by the garbage collector,
when it collects the memory. Concerning finalize, there are two
important points to remember: objects with an explicit disposal
function might not (in fact, shouldn't) be alive when it is
called, and it won't be called on local or static objects.
Calling both destructors just adds to the confusion. (For that
matter, speaking of "destructors" in this context may add to the
confusion, since the word more often applies to a concrete C++
language concept rather than the more general concept.)
Even at the time I was creating .NET applications with "C++
managed extensions" where every managed object had to be
allocated with __gcnew and left to be destroyed by the GC,
while you could define an explicit function to call so as to
free allocated resources explicitly when you wanted, and not
wait for GC to free the resources by calling the Finalizer
(the non-deterministic destructor that was the only kind of
destructor for managed classes), leaving all those Forms,
Buttons etc to the GC was a great relief, not having to worry
about explicitly releasing all those stuff.

Exactly. It's not something that is fundamentally necessary
(but then, neither are classes), but it's something that means
less work for the programmer, in the cases where it's
applicable. The cases where it's applicable are frequent
enough to justify adding it to the language, and offering it as
an add on isn't always a viable option. (To be really
effective, for example, the standard library must be GC aware,
with e.g. std::string using garbage collection, std::vector
null'ing freed elements, etc.)
So I think in normal PC GUI applications,garbage collection
has a place to make the programmer's life easier, where space
efficiency is not a primary concern (that is for the usual
user applications).
I remember some company or MS had ported Quake II to .NET and
the runt-time cost was only about 10%. So even Quake II where
speed is a primary concern, the GC didn't cause much trouble,
but rather it helped much.

GC is almost always a win in interactive software, since it will
run while you're waiting for user input. (This is also possible
with manual management, but it's not usually done. I don't know
why.) GC is also particularly effective when you have a lot of
short lived objects, which is, I suspect, typical of games
programs (although I'm not sure---I've never actually worked on
them).
GC has a place in the present and in the future, I think all
must come in terms with that. We can't stick in the past,
technology is moving forward. If you like it, use it, if you
don't like it, don't use it.

Yes. In practice, the C++ committee is at a juncture.
Independantly of any technical considerations, if the next
version of the standard doesn't support garbage collection and
threads, C++ is dead in the water---it will end up in the same
state as C, with a lot of older people used to it who continue
to use it, and argue in favor of it, because it's what they
know, but with less and less new applications being implemented
in it. (Alternatively, the major compiler vendors will simply
copy Microsoft, implement CLI, and call it C++. And the ISO
standard becomes irrelevant. And that's not a scenario I want
to see.)
 
J

James Kanze

But why add yet another facet?

I'm afraid I don't understand. I'm not adding anything. It's
all already there. About the only thing I'm suggesting is to
separate concerns, so the program can worry about each
separately, without being concerned about the other if it's not
relevant. (Note that there are special cases already where you
separate these concerns. It's an underlying principle in the
containers in the standard library, for example, where
initialization and allocation, as well as destruction and
deallocation, are rigorously separated.)
No, once written, smart pointer types can be used just like
any other, no extra work at all. One may have to choose which
type to use and there is always the risk of getting it wrong.

And you don't see a contradition in those two sentences? In my
work, most pointers are for navigation, and the navigational
possibilities are full of cycles. Using smart pointers
systematically would involve a great deal of extra analysis.
(Of course, in this context, there is no problem with regards to
when to delete the objects, and the garbage collection is mainly
a safety net, to allow trapping the use of a dangling pointer,
and not really necessary for reasons of memory management.)

There are other contexts where boost::shared_ptr (or my
pre-boost shared pointers) do work well, but again, I have to
think about them---I've identified the fact that the objects
don't need deterministic disposal (otherwise, I can't use
boost::shared_ptr), but I still have to consider possible
cycles, etc. It's not overwhelming, but it is a little bit of
extra work.
But the same could happen with a mix of GC and user managed
objects.

You can always neglect to correctly terminate the life of an
object. I've never found it to be a frequent problem,
however---less frequent than correctly handling some other major
events in the object lifetime. And boost::shared_ptr doesn't
really help, since you're likely to still have a pointer to the
object.

A more frequent problem is dangling pointers: the object's
lifetime has ended, but you've neglected to inform an interested
party. Garbage collection makes it easy to check for this,
whenever you use the pointer. (You can also make it work with a
combination of shared_ptr and weak_ptr, but it requires more
effort.)
As I said before, it's not GC I object to, it's mixing GC and
"conventional" memory management.

You don't mix them. All memory management is by garbage
collection.
I'd also object the mixing raw pointers with smart pointers
for dynamic objects.

In which case, you'll never use smart pointers, because there
just aren't enough different types of them to handle all of the
cases. (Unless you create a smart pointer which really does
nothing, for navigational purposes.)
The Document Object Model. I do a lot of work with XML and
XHTML documents!

Oops. I've actually used it, both in Java and in C++. I just
didn't recognize the name right off.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,130
Latest member
MitchellTe
Top