all groups > c# > october 2007 >
You're in the

c#

group:

Garbage Colletor


Re: Garbage Colletor Peter Duniho
10/9/2007 4:35:44 PM
c#: [quoted text, click to view]

You should love the GC. It's your friend.

If you don't love the GC, you probably just misunderstand it.

I don't know about the specific Outlook.Application object, but assuming
it has a Close() or Dispose() method, then you're not using it right.
If it doesn't have a Close() or Dispose() method, then your inability to
get it destroyed as you'd like is not the fault of the GC. It's the
fault of the Outlook.Application object.

As for your well-intentioned-but-not-quite-right attempts to get this to
work go...

[quoted text, click to view]

That is fine, as long as you don't need the Outlook.Application object
closed, freed, released, or otherwise discarded immediately. It sounds
as though you do though.

[quoted text, click to view]

Nor should it. Setting the reference to null simply disconnects the
reference and makes it unreachable from your program's data. Nothing
will happen to it until the GC needs to actually release the memory
being used by the object, and that might not be in awhile.

Setting a reference to null is _only_ for causing that reference to be
eligible for garbage collection. It essentially frees the managed
memory used by the object, but the GC isn't necessarily going to bother
to try to take advantage of that until it needs to.

If you have other cleanup you need to do, you are required to do that
before you discard the reference. You would do this via some method the
object class provides, and that method is usually Close(), Dispose() or
both.

[quoted text, click to view]

Your finalizer should call the Dipose() method, rather than doing
"dispose-like behavior" itself. Not that your finalizer actually
implemented "dispose-like behavior" (see below), but still.

And implementing a finalizer for a class that implements IDisposable is
a good idea, but the finalizer exists for redundancy. It should not be
considered the front line of defense, as it usually won't get called
right away, and might not ever be called.

[quoted text, click to view]

No doubt. You didn't do anything that would cause the object to be
destroyed. All you did was release your reference to it, which as I
mentioned doesn't necessarily do anything right away.

If Outlook.Application implements IDisposable, then you'll want to call
that in your own Dispose() method. And you'll want your finalizer to
call Dispose().

If Outlook.Application has a Close() method, then you may also want to
implement a Close() method on your class that calls Close() on your
Outlook object.

If Outlook.Application has neither Dispose() nor Close(), nor any other
sort of "destroy this object" method, then you're out of luck. That's
something you'll need to take up with the Outlook folks. It's a bug for
them to implement a .NET class that has or represents unmanaged
resources (e.g. a process) but doesn't provide a method for explicitly
disposing those resources.

I suspect, however, that the Outlook.Application object does have a
Close() or Dispose() or similar, and if so then using that is the
solution to your problem.

RE: Garbage Colletor Peter Bromberg [C# MVP]
10/9/2007 5:06:01 PM
You have to be really careful when working with COM Object Model .NET wrapper
classes for Office apps. For example the
Microsoft.Office.Interop.Outlook.Application class has a .Quit() method that
you should be calling to release the underlying COM coclasses when you are
done with it. Study the documentation carefully to ensure you are doing
everything right.
-- Peter
Recursion: see Recursion
site: http://www.eggheadcafe.com
unBlog: http://petesbloggerama.blogspot.com
BlogMetaFinder: http://www.blogmetafinder.com



[quoted text, click to view]
Re: Garbage Colletor Chris Mullins [MVP - C#]
10/9/2007 5:09:50 PM
[quoted text, click to view]

I just signed up to do a session on the Garbage Collector at the Silicon
Valley code camp later this month.

So many people seem to have problems with it....

--
Chris Mullins

Re: Garbage Colletor Peter Duniho
10/9/2007 7:41:07 PM
[quoted text, click to view]

While there's probably some truth in your observation, I have to say
that my experience has been more the opposite. Languages or platforms
that manage memory with a garbage collector are often viewed as "lazy",
"inefficient", "toy-like", etc. with many people scoffing at them.
Those people assert that memory management is best done explicitly by
the program, even though it requires more code.

I have to admit that, while I don't think I was ever so rigid in my
thinking, even I held those beliefs to some degree. The memory
management of .NET was always a concern to me, until I actually started
using it.

But now, I love the garbage collector. :)

And yes, there's no such thing as a free lunch. However, there
definitely is a such thing as efficient engineering. The lunch isn't
technically "free", but it sure costs a lot less if you do things
efficiently. And I do feel that .NET as a platform offers great
opportunity for much-improved efficiency in the development process.
There are even at least a few examples of where using .NET results in an
_implementation_ that is more efficient than what most developers might
come up with.

That's about as close to getting a free lunch as you're likely to see. :)

Re: Garbage Colletor Nicholas Paldino [.NET/C# MVP]
10/9/2007 8:46:50 PM
This is in addition to the call to ReleaseComObject that should be made
on the reference after the Quit method is called. Also in addition to all
the references to all the objects that are exposed by the properties of the
application, should they be called.

This is one of those situations where if you are making a good number of
calls to an unmanaged COM object and it is spitting out tons of references,
you might want to do a GC when you know the work is done and you aren't
holding on to references to any COM object wrappers.

--
- Nicholas Paldino [.NET/C# MVP]
- mvp@spam.guard.caspershouse.com

[quoted text, click to view]
Re: Garbage Colletor Larry Smith
10/9/2007 9:55:43 PM
[quoted text, click to view]

I can't help but laugh at the irony of this (not at you). Unmanaged
languages like C/C++ have been scoffed at for years because of memory
issues. Now people can't even handle a system that takes care of memory for
them. It goes a long way to demonstrate the complexities of our field
(there's no free lunch).

Garbage Colletor Johnny E. Jensen
10/9/2007 11:34:21 PM
Hellow

I'am not sure what to think about the Garbage Collector.

I have a Class OutlookObject, It have two private variables.
Private Microsoft.Office.Interop.Outlook.Application _Application = null;
Private Microsoft.Office.Interop.Outlook.NameSpace _Namespace = null;

The Constructor:
public OutlookObject()
{
_Application = new Microsoft.Office.Interop.Outlook.Application();
_Namespace = _Application.GetNameSpace("MAPI");
}
..... after this alot of members and properties

When i need to do something in outlook, I'll instanciate the OutlookObject
objOL = new OutlookObject();
And when i don't need Outlook anymore I'll use objOL = null;

In my head this should destroy the objOL and thereafter also the
_Application and _Namespace in the Garbage Collector, but it don't happens
all time.
So I'll found a way that should force the destruction, the use of finalizer,
so i put this into the OutlookObject() class:

~OutlookObject()
{
if ( _Application == null)
return;
else
{
_Application =null;
}
}

And I'll also tryed with the OutlookClass to dever from IDisposable class
and put in:
Public Dispose()
{
if ( _Application == null)
return;
else
{
_Application =null;
}
}

With both the same result - Outlook don't get destroyed before i'll close
the application.

The problem is that I'll use Outlook a lot of times within my application,
and with the Task Manager I'll some time see five or more Outlook instances
WHY?????
And if there is so many Outlook instances, they stay open event after I'll
close my application. WHY???


Kind regards

Johnny E. Jensen






Re: Garbage Colletor Christof Nordiek
10/10/2007 12:00:00 AM
"Peter Duniho" <NpOeStPeAdM@NnOwSlPiAnMk.com> schrieb im Newsbeitrag
news:13go42isos2ngfc@corp.supernews.com...
<snip>
[quoted text, click to view]

You should not call Dispose in the finalizer. When the finalizer runs, the
referenced object will also be eligible for collection resp. finalization,
and it's finalizer will run, maybe has allready run. But you should call
Dispose on the held objects in the Dispose method of the container.

Christof
Re: Garbage Colletor Willy Denoyette [MVP]
10/10/2007 12:00:00 AM
This is also true for unmanaged clients using "automation" interfaces to
interact with Office Applications. A native COM client that fails to call
"Quit" (all office application support this method) will result in the
server (here Outlook.exe) to stay loaded in memory. As you correctly said,
learn the object model before you even start "automating" Office (or any
other DCOM server like) applications.

Willy.



[quoted text, click to view]

Re: Garbage Colletor Johnny E. Jensen
10/10/2007 12:00:00 AM
Hello

Thanks to all the replies.

Outlook don't have a Close() or Dispose(),but it has a Quit() method. But if
Outlook is running (the normal GUI Outlook) and if I use the Quit() method
this (GUI outlook) is closing - a bit anoing for the user.

As Nicholas mentioned to use the ReleaseComObject - this does the trick. So
my OutlookObject class has a Dispose() method and here I use the
ReleaseComObject(_Application) and ReleaseComObject(_Namespace) and it
works.

Kind regards

Johnny E. Jensen


"Nicholas Paldino [.NET/C# MVP]" <mvp@spam.guard.caspershouse.com> wrote in
message news:CE4C280C-A8D4-4687-AA62-BE63B9035DD0@microsoft.com...
[quoted text, click to view]

Re: Garbage Colletor Willy Denoyette [MVP]
10/10/2007 12:00:00 AM
Do you mean you are connecting to a running instance?
Note that even without this ReleaseComObject calls, there should be NO new
instance of Outlook getting created.
What kind of application is this (Windows, Console, other)?

Willy.



[quoted text, click to view]

Re: Garbage Colletor Göran_Andersson
10/10/2007 1:34:35 AM
[quoted text, click to view]

That's just because you expect it to do something that it's not supposed
to do. ;)

[quoted text, click to view]

It doesn't. It only makes the object available for garbage collection.

Garbage collections happen at times that the garbage collector decides,
and not every time an object is available for garbage collection. Also,
when a garbage collection happens, that doesn't guarante that all
available objects are collected. The garbage collector can decide that
it's not efficient to collect some of the objects at that time.

[quoted text, click to view]

Actually, at the exact moment that the objOL can be garbage collected,
every object that it references (and isn't referenced somewhere else)
can also be garbage collected.

[quoted text, click to view]

A finalizer is not useful if you want to control when the objects are
released. An object that has a finalizer will be put in the freachable
queue instead of being collected. A background thread then runs the
finalizer methods in the objects one after one, but you have no control
over when this happens.

If it takes too long to go throught the freachable queue when the
application ends, the rest of the objects will just be discarded without
finalization, so it's not even guaranteed that the finalizer will ever run.

[quoted text, click to view]

Why checking? Setting the reference to null again doesn't do any harm.

[quoted text, click to view]

Why a return statement here? It's totally superflous as there is no more
code from this point to the end of the method.

[quoted text, click to view]

Did you actually call the Dispose method? It's not called automatically.

[quoted text, click to view]

--
Göran Andersson
_____
Re: Garbage Colletor John Duval
10/10/2007 4:27:47 AM
[quoted text, click to view]

Just a point of clarification for other people who might misread your
post -- calling Dispose from the finalizer is a common pattern and
it's perfectly ok to do. You just need to make sure that when you do
it, your Dispose method doesn't try to touch other managed objects
when called from the finalizer. As you point out, these other managed
objects might have already been cleaned up, so calling them will lead
to errors. The pattern I've seen most often is to have Dispose( ) and
the finalizer both call Dispose(bool disposing). When calling from
Dispose( ), pass disposing=true and call GC.SuppressFinalize(this).
When calling from the finalizer, disposing=false. Inside Dispose(bool
disposing), you should dispose other managed resources only if
disposing=true.

John

Re: Garbage Colletor Larry Smith
10/10/2007 7:40:50 AM
[quoted text, click to view]

This is simply human nature at work. People who master any complex skill
will generally feel superior to those who master a "lesser" skill (one
that's less complicated). They then convince themselves that the lesser
skill itself must also be inferior in some way. It's a fallacious argument
but most are guilty of it to some extent.

[quoted text, click to view]

As far as handling resources is concerned however, I think C++ has always
been unfairly maligned. Not only is it much less error-prone than people
believe (IMHO), the RAII paradigm itself is a cleaner design compared to a
GC system (again, IMHO). While it would be very difficult for anyone to
technically [dis]prove it (I certainly can't), I base it solely on my own
experience.

Re: Garbage Colletor Peter Duniho
10/10/2007 10:02:56 AM
[quoted text, click to view]

I have the impression that you feel it's also a fallacious argument that
C/C++ is deserving of scorn and scoffing. Which is fine...I think
there's a lot of pointless scorning and scoffing going on in both
directions.

My point was simply that the scorn and scoffing isn't limited to the
C/C++ direction. It's also directed at garbage collection, and is just
as fallacious in that case as the case you mention.

[quoted text, click to view]

Well, my experience is the opposite. It is simply not possible to have
a memory leak in a garbage collection system. But memory leaks abound
in conventionally written C/C++ applications. I see it all the time.

There are ways to write code in a way that helps ensure against memory
leaks, but these aren't things that the language provide. They are
things that the developer must implement oneself (for example, code in
the debug build that actually tracks memory allocations and requires
idle-time consistency checks).

Now, does that mean that C++ is as error-prone as people believe? I
don't know. What do people believe? How do you measure that? But in
terms of C++ being more error-prone than a garbage collecting system
goes, I'd say that's easily observed and demonstrated.

IMHO the only real error likely to come up with respect to memory
management is, by definition, failing to manage memory correctly. That
is, either failing to allocate memory when you need it, or failing to
release it when you're done. The former is a trivial problem, easily
solved in any paradigm, while the latter simply doesn't exist in a
garbage collecting system.

So it's easily proven that, as long as one is looking only at those
kinds of errors, C/C++ is trivially more error-prone than a
garbage-collecting system.

Is the explicit allocation-and-release of C/C++ itself unwieldy and
excessively error-prone? No, I don't think so. I agree with you that
it's actually not hard to use, even while ensuring correct code. But it
is very unforgiving of carelessness, and unfortunately there are a lot
of programmers out there whose primary identifying characteristic is
carelessness.

I don't know how to evaluate "cleaner design" in this context. If
you're talking about the design of the memory manager, I'd have to agree
that a GC memory manager is more complicated, less "clean". On the
other hand, that only needs to be written once. I would definitely
disagree if you are trying to claim that the design of code written that
_uses_ the memory manager is "cleaner" in C/C++ than if using a GC
memory manager. What could be cleaner than not having to write the code
in the first place?

But really, the only thing I was pointing out is that just as you've
observed people scoffing at the C/C++ paradigm, I have observed people
scoffing at the garbage collection paradigm. It's not as one-sided as
your post seems to imply, and in fact (maybe as a result of the
environment in which I work) my experience has been that I see more
people criticizing the GC paradigm than the other way around.

Re: Garbage Colletor Peter Duniho
10/10/2007 10:08:34 AM
[quoted text, click to view]

As John says, that's not true. I may not have been clear enough in my
own post, but you should call your own Dispose() in the finalizer to
ensure that unmanaged resources in your own object are released.

But really, the situation here isn't about the finalizer at all. As I
said, that's a backup plan for when things aren't coded right.

The non-finalizing scenario (indicated by the boolean passed in) in the
Dispose() method of the class should release managed and unmanaged
resources, and should call the appropriate method on the
Outlook.Application object (that is apparently the Quit() method, as
Peter Bromberg has pointed out) to release that object.

And the OP's code should call his own class's Dispose() method directly,
rather than relying on the finalizer.

I don't know whether the Outlook.Application finalizer also calls
Quit(), but if it doesn't, that would mean it's essentially an unmanaged
resource and your own (that is, the OP's) Dispose() method should call
Quit() even in the finalizing case.

Re: Garbage Colletor Chris Mullins [MVP - C#]
10/10/2007 11:01:14 AM
[quoted text, click to view]

Well, for what it's worth, in a 3 hour presentation on application Tuning,
about 1/2 that time is spent on Memory Leaks, and how to track them down.

Just like in C/C++ land, they're due to a user misunderstanding how GC works
and making a silly mistake. For some reason, the people who most often seem
to get bitten are novice devs who discover they really like static
variables...

.... so I spend quite a bit of time using a Memory Profiler, and showing them
how to read it's output.

My favorite leaks invoke making my laptop (with 2GB of memory) generate an
OOM while only actually allocating a few hundred KB of memory. (I have a
very nasty pinning / fragementation demo that really drives home the
issue...)

--
Chris Mullins


Re: Garbage Colletor Chris Mullins [MVP - C#]
10/10/2007 11:39:11 AM
[quoted text, click to view]

public class MyWebService
{
private static List<Byte[]> _myReceivedData;

private void DataFromAWebService(Byte[] rawData)
{
_myReceivedData.Add(rawData);
// Do operations
}
}

I see "innocent" code that looks like this all the time. The List, because
it's static, is never cleaned up.

People add data into it, and forget the list is static. They exepect that
when the class instance of MyWebService goes away, that the list of received
data will as well.

It's a really simple error, but I see it again and again and again...

--
Chris Mullins

Re: Garbage Colletor Peter Duniho
10/10/2007 1:39:55 PM
[quoted text, click to view]

I guess that depends on your definition of "memory leak". Mine is such
that a garbage collection system specifically precludes them.

I understand how you might call your example of a static variable that
isn't released a "memory leak", but the memory hasn't become orphaned or
anything. The application simply failed to release it, and the same
kind of "leak" exists regardless of the type of memory management (ie it
would be just the same error for a CRT-based program to fail to release
that memory).

To me, a true "memory leak" is a situation in which the memory is gone
forever for that process. There's simply no way for any code anywhere
to ever recover it. Whether or not such code exists isn't relevant to
my use of the term. It's whether it _could_ exist.

At the very least, it seems to me that in your presentation you should
make clear the differing definitions of "memory leak".

Re: Garbage Colletor Peter Duniho
10/10/2007 2:05:08 PM
[quoted text, click to view]

I certainly agree there. But one system is definitely more resilient to
programmer error.

[quoted text, click to view]

I think we've found ourselves in vehement agreement on that point
previously. I'm still in vehement agreement with you on it. :)

[quoted text, click to view]

Well, the thing is...once you no longer have a reference to a memory
resource, it _is_ released. Just because the GC hasn't run, that
doesn't mean the memory isn't available. It just means that the GC
hasn't gotten around to moving it into the collection of memory that is
_immediately_ available for use.

Logically speaking, the memory is still in fact available, the moment
you release your last reference to it.

[quoted text, click to view]

IMHO, it's a mistake to think of the "using" statement, the finalizer,
or IDisposable as related to a C++ destructor. It's only "ugly"
compared to it if you are treating them the same.

The "using" statement and IDisposable exist for one purpose: to
explicitly release resources held by an object without releasing the
object itself. Within that one purpose, there are two sub-categories of
types of resources that may be released: managed, and unmanaged.

Obviously the only reason the unmanaged category even exists is that
..NET runs on top of a system that is not entirely managed code. If all
of Windows was based on a garbage collection system, that category
wouldn't exist.

So, let's consider only the managed category. In this case, it's
beneficial to be able to tell an object "let go of the resources you're
holding" without releasing that object itself. But this is again not
comparable to a destructor, because the object itself still exists. It
hasn't been released or destroyed and it is theoretically possible that
it could be reused. This is much more comparable to a C++ class that
hasn't been deleted, and thus hasn't been destroyed, but which has some
sort of "release your resources" function that has been called.

[quoted text, click to view]

And in C# not having a reference to an object is nicely symmetrical to
creating a reference to an object. The latter initializes the object
and the former cleans it up. In a purely managed environment, releasing
a single reference to an object is exactly equivalent to the C++
paradigm of having to call a destructor where individual resources
within the object have to be explicitly cleaned up.

In fact, the garbage collection model is, at least for that particular
operation, much more efficient, because there's no need to go through
the entire object cleaning things up. Everything that object refers to
is automatically released, with a single nulling, or leaving scope, of
the last variable holding a reference to that object.

Overall, I suspect the efficiency is about the same. The extra work
that the C++ model has to do initially is balanced by the extra work the
garbage collector will have to do later.

[quoted text, click to view]

Likewise, using GC as soon as an object is no longer referenced, any
managed resources no longer exist. They are automatically released when
that object referencing them is.

[quoted text, click to view]

But why do you care when the GC is going to occur? It only happens when
it needs to, or when it gets the opportunity to, and there should be
nothing in your code that depends on or otherwise relies on when, if at
all, garbage collection happens.

In a multi-tasking operating system like Windows, there are a wide
variety of things that occur and which you have no control over. A
garbage collection system simply introduces a new instance to this
already very broad category of components.

[quoted text, click to view]

I don't understand that at all. A person who isn't used to releasing a
reference to an object when they are done with it isn't going to be used
to deleting a C++ object when they are done with. Conversely, a person
who can remember to delete a C++ object when they are done with it can
remember to release a reference to a .NET object when they're done with it.

[quoted text, click to view]

What kind of resource? If you're talking about a managed resource, then
simply releasing the reference to the referencing object is sufficient
to release the resource.

If you're talking about an unmanaged resource, well...that's not a
problem inherent with garbage collection. It's a natural consequence of
mixing a garbage collection system with a traditional alloc/free system.
That problem _only_ exists because of the traditional alloc/free
system; it hardly seems fair to blame it on the garbage collection paradigm.

[quoted text, click to view]

This one I understand even less. If a deep copy is required but a
shallow copy is done, this is if anything more dangerous in the C++
model, because the referenced data can be freed by any one copy of the
instance. This just won't happen in a garbage collection system.

With a GC system, you still have the potential issue of having multiple
instances refer to the same data, but this issue exists regardless of
the memory management model. It's an implementation problem, not a
memory management problem.

[quoted text, click to view]
Re: Garbage Colletor Chris Mullins [MVP - C#]
10/10/2007 2:12:49 PM
[What's a Memory Leak?]

[quoted text, click to view]

The definition will vary, but even then, saying GC precludes them isn't
quite right.

There are all sorts of strange corner cases. Off the top of my head:
- Static variables are never collected off the high frequency heap
- The Large Object Heap isn't compacted

Think of the fun you could have allocating large byte arrays in static
constructors - memory would come off the LOH, and would likley never be able
to be reclaimed....

If we bring in Win32 & Interop, many corner cases spring up, the most common
one being fragmentation due to pinning.

[quoted text, click to view]

I think that's a misleading definition.

A leak, even in C/C++ land, is generally characterized by an application
bug. Sometimes it's as simple to fix as, "use an auto pointer", and other
times it's very complex. The same seems to hold true in .Net.

[quoted text, click to view]

Nah. These are usually people new to .Net, and the level for them is just
right. More detail just becomes confusing...

--
Chris Mullins

Re: Garbage Colletor Larry Smith
10/10/2007 2:38:31 PM
[quoted text, click to view]

It's a religious issue and both have their pros and cons. While C++ may be
more error-prone than a GC system however (for releasing resources), there
need not be a significant difference. The problem is almost entirely a human
one. It's extremely easy to handle resources in C++ as you stated but the
language's reputation has often suffered because of its practioners (most
programmers being very poor at what they do). My own opinion however is that
in the hands of those who really know what they're doing (few and far
between), RAII is a cleaner approach than a GC system. By clean I mean it's
more natural to release your resources in a destructor than to wait for a GC
to run (not to be confused with easier or less error prone - it's clearly
not). The "using" statement for performing this in C# for instance (or even
worse, a "finally" block), is ugly compared to a C++ destructor. The
destructor is nicely symmetrical with its constructor. The latter
initializes the object and the former cleans it up. This occurs immediately
when an object goes out of scope so your resources only exist for as long as
they're needed. It's all very well controlled and understood. You know
exactly when clean up is going to occur and need not worry the timing of a
GC. In fact, a GC itself can even promote sloppy behaviour. People become
so used to it doing the clean up that they can neglect to explicitly clean
something up themselves when the situation calls for it (such as immediately
releasing a resource that might later cause something else to fail if it
hasn't been GC'd yet). Or people might always perform shallow copies of
their objects where a deep copy is required (since it's just so easy). In
C++ you have to think about these things more but that deeper thinking
process also sharpens your understanding of the issues IMO (and hopefully
the design of your app). Of course this is all a Utopian view of things. In
the real world most programmers require the handholding that a GC offers.

Re: Garbage Colletor Peter Duniho
10/10/2007 3:11:51 PM
[quoted text, click to view]

As I said, my definition does.

[quoted text, click to view]

Do you mean there is some programming error that would cause that to
happen? Can you be more specific?

[quoted text, click to view]

But those would be arrays the application still holds a reference to,
no? If not, why wouldn't they be able to be reclaimed?

[quoted text, click to view]

I'm specifically talking about memory leaks. There are, of course,
other ways to interfere with memory allocations, such as fragmenting the
heap. That's outside the scope of what I'm talking about.

[quoted text, click to view]

Well, I'm happy to agree to disagree. But just as I suspect there's at
least one person who agrees with your viewpoint, I think it's likely
there's at least one person who agree with mine. We're talking about a
semantic issue here, and those are almost never black & white.

Even if you don't agree with a particular viewpoint, you should at least
take it into account.

[quoted text, click to view]

Agreed. But I don't agree that all memory-related bugs are examples of
"leaks". A leak is a bug, but not all bugs are leaks.

[quoted text, click to view]

Your choice, of course. However, from my own personal point of view,
the fact that I might be new to .NET does not negate any previous
experience I might have, nor does it change how I view the definition of
a "memory leak".

Whether that's an issue in your presentation depends more on how many,
if any, of your audience shares my viewpoint than on how much, if
anything, they already know about .NET.

Re: Garbage Colletor Peter Duniho
10/10/2007 4:04:43 PM
[quoted text, click to view]

But those two functions aren't doing the same thing.

The C# equivalent to the CPlusPlusFunc() you posted is this:

void CSharpFunc()
{
MyExpensiveObject obj = new MyExpensiveObject();

// ...
}

As I pointed out, "using" is used for a completely different purpose.
It's a mistake to think of it as the same as a C++ destructor.

In fact, in .NET the runtime is smart enough to recognize when a
reference is not actually used throughout a function, and will in that
case release the reference _earlier_ than would be the case for C++.

So not only is the code no "uglier", the lifetime of the object in .NET
much more exactly matches its actual use than it does in C++.

Re: Garbage Colletor Peter Duniho
10/10/2007 6:50:21 PM
[quoted text, click to view]

So what? The finalizer isn't part of the behavior of a correctly
written program. You should forget all about the finalizer. It only is
relevant when you have a bug.

[quoted text, click to view]

I have not found it to be so and, even if it were, as I pointed out
whatever cost garbage collection has is at least partially, if not
completely, mitigated by the fact that releasing an object is a
constant-order operation (O(1)), whereas it's O(n) for conventional
free/alloc implementations (where n is the number of individually
referenced objects in the tree rooted by the object being released).

People who know a lot more about the garbage collector than I do have in
this very newsgroup provided very good explanations as to how very
efficient garbage collection actually is. The garbage collector doesn't
take nearly as much time to do its work as you seem to think it does.

[quoted text, click to view]

That is simply not true. As I have pointed out several times already,
the only time you need to release your resources explicitly is when you
have unmanaged resources. And that's an artifact of mixing GC with
free/alloc. It's not a problem inherent in garbage collecting.

One more time: if your object references only managed data, then the
instant your object is no longer referenced itself, ALL memory resources
referenced by that object are also no longer referenced, and are
released in the same instance the root level object is.

The finalizer is completely irrelevant and in fact would not even need
to exist in a purely garbage-collected environment. It exists only
because of the unmanaged, non-garbage-collected resources and it's
either a mistake or an outright lie to try to point to the finalizer as
some inherent problem with garbage collection.

I'll assume that in this case, it's just a mistake on your part. But
you really should stop bringing it up. It's just not relevant.

[quoted text, click to view]

Because it's true. An object is eligible for garbage collection after
the last statement that references it. The garbage collection need not
wait for the variable referencing the object instance to go out of
scope, or be set to null, or anything else like that.

And of course, as I have already pointed out, the moment the object is
eligible for garbage collection, it is effectively released. It doesn't
have to actually be collected for it to be considered logically returned
to the collection of available memory resources.

[quoted text, click to view]

And again, you need to forget about the finalizer. It's not relevant at
all in this part of the discussion.

[quoted text, click to view]

But those statements are also irrelevant to this part of the discussion.
They exist for explicit releasing of resources, but they aren't needed
unless you a) want to keep the object for later reuse, but release
resources (in which case it's exactly the same as C++) or b) you want to
ensure that unmanaged resources are also freed (in which case it's not
at all relevant to the question of the general paradigm of garbage
collection).

In other words, in neither case does "using" or Dispose() have anything
to do with any difference there might exist between the free/alloc
paradigm and the garbage collection paradigm.

Re: Garbage Colletor Larry Smith
10/10/2007 6:53:04 PM
This is what I mean by "ugly":

void CSharpFunc()
{
using (MyExpensiveObject obj = new MyExpensiveObject())
{
// ...
}
}

This OTOH achieves "deterministic finalization" automatically and it's
syntactically cleaner:

void CPlusPlusFunc()
{
MyExpensiveObject obj;

// ...
}

Re: Garbage Colletor Martijn Mulder
10/10/2007 8:08:05 PM
Chris Mullins [MVP - C#] schreef:

[quoted text, click to view]

Can you give us a small example when and how a static variable can cause
Re: Garbage Colletor Larry Smith
10/10/2007 8:55:56 PM
[quoted text, click to view]

In fact they are doing the same thing for all intents and purposes. I have
no reason to allocate my C++ object on the free-store (heap) in this
scenariio but even if I did, I can always assign the pointer to an
"auto_ptr" or some other smart-pointer object. It's still syntactically
cleaner than the C# version. In practice however you need not rely on local
pointers most of the time (or even "new" for that matter) so it's usually a
non-issue.

[quoted text, click to view]

I realize it's not the same thing. It's just syntactic sugar for a call to
"Dispose()". It's intended to "destroy" the object however and once called,
you shouldn't access the object again.

[quoted text, click to view]

When an object's reference is no longer accessible, the call to "Finalize()"
is non-deterministic. It normally happens when memory exhaustion occurs
which triggers the GC. In theory however it might never occur so
"Finalize()" itself might never be called. GC is also a very expensive
process. The GC even suspends all threads in the application to carry out
its work by injecting the code to do this at strategic locations.
Implementing a proper clean-up routine also raises a host of other
housekeeping chores such as calling "SuppressFinalize()" in your "Dispose()"
method, handling multiple calls to "Dispose()", etc (note that both
"Dispose()" and "Finalize()" should also be routed through the same common
cleanup function). The bottom line in any case is that you have no choice
but to release your resources explicitly if you can't wait for the GC to
invoke "Finalize()". The syntax for that is unsightly however (IMO).

[quoted text, click to view]

How do you arrive at that conclusion. The call to "Finalize()" is
non-deterministic but the call to a C++ destructor isn't. That occurs as
soon as it exits its scope which you have complete control over. The
destructor is also syntactically cleaner than relying on a "using" statement
or calling "Dispose()" directly.

Re: Garbage Colletor Enkidu
10/11/2007 12:00:00 AM
[quoted text, click to view]
Some languages require it and some people moving from those languages
would feel better with it there. Sure they could do it the C# way and
leave it out, but it causes no problems, does it.

Also, more pertinently, if you should come along and modify the code, by
wrapping it in an 'if' for example and also put code after it, then you
have to remember to insert the 'return' if it is not already there.

If you modify the routine to return something, the return is already
there to be modified.

I'm not saying that these are particularly *good* reasons, mind you..

Cheers,

Cliff

--

Have you ever noticed that if something is advertised as 'amusing' or
Re: Garbage Colletor Göran_Andersson
10/11/2007 12:24:13 AM
[quoted text, click to view]

On the other hand, you could just as well add code that you actually
want to be executed in both cases, so then you would have to remember to
remove the return statement. :)

[quoted text, click to view]


--
Göran Andersson
_____
Re: Garbage Colletor
10/11/2007 5:44:07 AM
[quoted text, click to view]

<snip>

I suspect Pete's point is that in a program without a bug, the
finalizer won't be run - because Dispose will have been called
explicitly. Finalizers usually just provide a safety net *in case* you
have bugs.

[quoted text, click to view]

So in that case, you have a bug. If your code fails to call Dispose on
something that implements IDisposable (and does so accidentally,
rather than through absolute and correct knowledge that Dispose does
nothing for that case) then you have a bug, and a finalizer *may* get
you out of a scrape.

[quoted text, click to view]

Absolutely, although in those cases they shouldn't usually implement a
finalizer as well.

Jon
Re: Garbage Colletor Larry Smith
10/11/2007 8:35:02 AM
[quoted text, click to view]

Your're focusing the crux of your argument on some theoretical notion that
we live in a world without unmanaged resources. Well explain to me what
resources you think the .NET classes are handling behind the scenes. This is
..NET for "Windows", not .NET for "Peter's purely managed OS X". In the world
we both live in the finalizer is a fact of life. What do you think the
"Note" section here means for instance:

http://msdn2.microsoft.com/en-us/library/system.drawing.font.dispose.aspx

I'm not aware of any "bug" so should I still "forget all about the
finalizer". What if I'm holding an object that stores a network resource of
some type, possibly using a native .NET class that holds this. If I don't
explicitly release it then it might never get releasesd and my app might
eventually fail somewhere (after creating enough instances). In fact, even
your own objects should implement "Dispose()" whenever they store references
to other objects that implement "Dispose()". The focus of my previous posts
have been on this very issue. I'm talking about the (cleaner) syntax of
using a C++ destructor versus finalize/dispose for releasing *unmanaged*
resources.(not objects that live entirely on the managed heap and are
therefore cleaned up automatically).

Re: Garbage Colletor Larry Smith
10/11/2007 9:50:29 AM
[quoted text, click to view]

The term "bug" in this context is used somewhat loosely however. Neglecting
to call "Dispose()" isn't a bug unto itself unless absolutely mandated by a
particular object. And even then it only becomes a latent bug as you alluded
to (which may never surface). Why invite trouble however. It's probably a
best practice to always invoke "Dispose()" given the intended purpose of
this function. In any case, this is just a side-issue to what we've been
discussing (C++ destructor syntax vs finalize/dispose)

Re: Garbage Colletor Larry Smith
10/11/2007 10:52:16 AM
[quoted text, click to view]

Probably the most reasonable interpretation anyway.

Re: Garbage Colletor John Duval
10/11/2007 2:30:54 PM
[quoted text, click to view]

Chris,
For what it's worth, I'm with Pete on this one. It's probably due to
the fact that I have C++ background, but to me a memory leak means a
very specific thing, which is that the memory has been orphaned and
there is no reference anywhere that can be used to recover it. Not
all increases in memory usage are memory leaks.

Even if I were new to .NET, I think it would be helpful to be a little
more specific about your definition of memory leak. Even people who
are new to .NET have heard that one of the big benefits is garbage
collection which prevents memory leaks.
John
Re: Garbage Colletor Marc Gravell
10/11/2007 3:37:10 PM
[quoted text, click to view]

IMO, implementing IDisposable is just such a mandate - by the
encapsulation principle, i.e. you shouldn't know or care what goes on
under the covers.
It would be nice if the language had some way of enforcing this, and
transferring ownership in the case of factory methods, or handing
ownership to a wrapper object that was itself IDisposable. Oh well.

Marc

Re: Garbage Colletor Ben Voigt [C++ MVP]
10/11/2007 4:14:50 PM
[quoted text, click to view]

I know exactly what you're getting at, but you and Peter are both wrong.

A memory leak is memory that remains unavailable for reuse after it is no
longer needed. This is the only definition of memory leak that makes sense.
After all, by your definition, this isn't a memory leak (C++):

void f(void)
{
int* p = new int[1024];
}

Of course that is a memory leak. And so is this (C#):

class C
{
private static int[] a;
static C() { a = new int[1024]; }
}

C c = new C();

These cases are *identical*. Both int arrays are still accessible (in
native code, via HeapWalk, in managed, via reflection on the Type object
which, once loaded, is never freed until the AppDomain unloads), but are
also totally useless in the context given.

Re: Garbage Colletor Ben Voigt [C++ MVP]
10/11/2007 4:19:14 PM

[quoted text, click to view]

Not "a person who can remember to delete a C++ object:". A good programmer
knows how to use a reference-counting smart pointer, where cleanup is just
as automatic as with a garbage collector (and sometimes moreso). A smart
pointer as a static member is just as bad as with GC, but at least C++ smart
pointers do the right thing with local variables and exceptions or early
exits -- automatically.

Re: Garbage Colletor Ben Voigt [C++ MVP]
10/1