GC.Collect can be trusted?

W

Ward Bekker

Hi,

I'm wondering if the GC.Collect method really collects all objects
possible objects? Or is this still a "smart" process sometimes keeping
objects alive even if they can be garbage collected?

I need to know because I'm looking for memory leaks in an application.

It would be really helpful to be able to determine if an object after
manually invoking the GC.Collect is only kept alive because it still
being referenced by other alive objects in contrast to being alive
because the GC.Collect didn't found it necessary to collect the object,
even when asked explicitly.

Regards,

Ward
 
D

DeveloperX

Hi,

I'm wondering if the GC.Collect method really collects all objects
possible objects? Or is this still a "smart" process sometimes keeping
objects alive even if they can be garbage collected?

I need to know because I'm looking for memory leaks in an application.

It would be really helpful to be able to determine if an object after
manually invoking the GC.Collect is only kept alive because it still
being referenced by other alive objects in contrast to being alive
because the GC.Collect didn't found it necessary to collect the object,
even when asked explicitly.

Regards,

Ward

I believe it attempts to reclaim all objects. If you've got a memory
leak though you might want to take a look at the CLR profiler

http://www.microsoft.com/downloads/...52-d7f4-4aeb-9b7a-94635beebdda&displaylang=en

thats for 1.1, there's a link for 2.0 at the bottom..
 
G

Guest

Ward,
Using GC.Collect to attempt to identify memory leaks is not a realistic
solution. Memory Leaks are generally caused by developers. Especially when
they fail to dispose of objects that need to be disposed, or if they fail to
implement similar patterns on their own objects where necessary.
There are a number of memory profilers you can use to track down this type
of issue. As well, FXCop can help you to identify bad coding patterns.
Peter
 
W

Ward Bekker

Let me explain a bit more. I am using a memory profiler, and see several
live objects that should be collected at the time I created a memory
snapshot.

I need to be sure that they are _really_ live objects because of a
mistake in our own code, or that they just alive because the GC.Collect
can't be trusted.
 
C

Christopher Ireland

Ward said:
Hi,

I'm wondering if the GC.Collect method really collects all objects
possible objects? Or is this still a "smart" process sometimes keeping
objects alive even if they can be garbage collected?

I need to know because I'm looking for memory leaks in an application.

I think you will find the following article useful and interesting:
http://support.microsoft.com/kb/318263/en-us

"Because of the garbage collection package that is implemented in the
Microsoft .NET Framework, it is not possible to have a memory leak in
managed code. This suggests two questions: How then can a memory leak occur?
Why does it appear that you have a memory leak?"
 
W

Ward Bekker

Hi Cristopher,

My definition of a memory leak for managed frameworks:

All objects that should be garbage collected, but can't because they are
still referenced by other objects that will not be garbage collected ;-)
 
C

Christopher Ireland

Ward said:
My definition of a memory leak for managed frameworks:

All objects that should be garbage collected, but can't because they
are still referenced by other objects that will not be garbage
collected ;-)

The article I quoted suggests to me that there are no managed objects that
can't be garbage collected!
 
C

Christof Nordiek

"Because of the garbage collection package that is implemented in the
Microsoft .NET Framework, it is not possible to have a memory leak in
managed code. This suggests two questions: How then can a memory leak
occur? Why does it appear that you have a memory leak?"

Though garbage collection is very usefull to provent memory leaks, this
quote is a bit to optimistic. Sure ther can be memory leaks in managed code.
E.g. all static fields aren't collected. So any object directly or
indirectly referenced by a static field wouldn't be collected. Also any
variables very high in the call stack can prevent referenced object from
being collected, (though the lifetime of a variable can be shortened by the
compiler.)
By this a memory leak in managed code can easily construckted.

But it's very unlikely to happen in real code. And it's much 'harder' to do
it purposelessly in managed code, than in unmanaged colde.

Regards
Christof
 
C

Christopher Ireland

Christof said:
Though garbage collection is very usefull to provent memory leaks,
this quote is a bit to optimistic. Sure ther can be memory leaks in
managed code. E.g. all static fields aren't collected. So any object
directly or indirectly referenced by a static field wouldn't be
collected. Also any variables very high in the call stack can prevent
referenced object from being collected, (though the lifetime of a
variable can be shortened by the compiler.)
By this a memory leak in managed code can easily construckted.

Interesting. Are you suggesting that the Microsoft Article 318263 I posted a
link to is somehow incorrect or misleading? Do you have any Microsoft links
which specifically refer to memory leaks in managed code?

This is an important area for me to clear up with my clients and I would
appreciate being able to quote Microsoft sources.
 
N

Nicholas Paldino [.NET/C# MVP]

Ward,

That's the thing though, if the object that you think should be garbage
collected is referenced by another object which is rooted (meaning you are
holding onto it some other way) and so on, then your object should NOT be
garbage collected. This is well-defined behavior for GC systems.

If you feel that your object should be collected at any time, then what
you really want are weak references. Take a look at the WeakReference
class.

Also, remember, if you have a delegate that points to a method on an
instance, then that instance is not eligible for GC. So if you subscribed
to an event, and didn't unsubscribe, then that instance is going to live on
as long as the object that publishes the event lives. A lot of developers
forget about this.

Hope this helps.
 
J

Jon Skeet [C# MVP]

That's the thing though, if the object that you think should be garbage
collected is referenced by another object which is rooted (meaning you are
holding onto it some other way) and so on, then your object should NOT be
garbage collected. This is well-defined behavior for GC systems.

Yes, and I think that's Ward's point. He sees (in the profiler) an
object which he know should be garbage. There are three possibilities
here:

1) It is garbage, but it hasn't been collected.
2) It's not garbage, but should be, and there's a bug.
3) It's not garbage, and shouldn't be.

I believe the original question was trying to determine whether
calling GC.Collect() is a good way of removing option 1 from the
equation.
I suspect it's a good but not absolutely foolproof way. Calling
GC.Collect(), then GC.WaitForPendingFinalizers(), then GC.Collect() is
probably better, but I suspect there are still some situations where
it wouldn't help.

Jon
 
C

Christof Nordiek

Christopher Ireland said:
Interesting. Are you suggesting that the Microsoft Article 318263 I posted
a link to is somehow incorrect or misleading? Do you have any Microsoft
links which specifically refer to memory leaks in managed code?
Atleast it is a bit inaccurate about what is a memory leak.

Look furhter down in the same article:

"Additionally, a project may only appear to have a memory leak. This
condition can occur if many large objects (such as DataTable objects) are
declared and then added to a collection (such as a DataSet). The resources
that these objects own may never be released, and the resources are left
alive for the whole run of the program. This appears to be a leak, but
actually it is just a symptom of the way that memory is being allocated in
the program.

For example, you have a DataSet. Every time that a new query is run, you add
a new DataTable element to that DataSet to hold the data that is returned.
If there are large amounts of data that you never dispose of, the data stays
alive as long as the DataSet is still in use. If this occurs enough times,
it is possible to run out of memory. This is not a memory leak, but instead
it is a problem in managing the memory."

If all the data loaded into the dataset mentioned is really needed still in
memory than this application simply needs so much memory and I's guess, it's
very badly designed.

On the other hand, if the older datatables aren't used anymore, but simply
remain in memory because they are referenced by the dataset, then I surely
would call this a memory leak.

What you should be cautious about is, if a shortly used objects are
referenced by a long living objects. For all if the objects are great and/or
there are much of them. Then should not remove those references to late or
forget to remove them at all.

HTH
Christof
 
P

Peter Duniho

The article I quoted suggests to me that there are no managed objects
that can't be garbage collected!

Anything to which a reference still exists "can't be garbage collected".
Which is good, because otherwise all of your objects would disappear the
first time the garbage collector ran. The garbage collector collects
anything that *can* be garbage collected, and so obviously there must also
be things that "can't be garbage collected" (that is, those things that
you're still using).

That's what Ward was talking about.

You obviously are really talking about "UNREFERENCED managed objects that
can't be garbage collected", and I'd agree there are none of those. But
it seems to me that Ward made it pretty clear that's not what he's talking
about. He's talking about objects to which he still has references, but
*shouldn't*, and so they stay allocated even though they should have been
released.

It's a fundamentally different way of looking at the idea of a "memory
leak", but it's pretty much the only kind of memory leak you'd have with
managed objects and is still an example of a coding error (it's just that
the references are being kept when they shouldn't be, instead of being
lost when they shouldn't be :) ).

I hope that clarifies things.

Pete
 
J

Jon Skeet [C# MVP]

Christof Nordiek said:
Atleast it is a bit inaccurate about what is a memory leak.

Look furhter down in the same article:

"Additionally, a project may only appear to have a memory leak. This
condition can occur if many large objects (such as DataTable objects) are
declared and then added to a collection (such as a DataSet). The resources
that these objects own may never be released, and the resources are left
alive for the whole run of the program. This appears to be a leak, but
actually it is just a symptom of the way that memory is being allocated in
the program.

Basically what it's saying is that bugs can cause things which look
like memory leaks. Quite what it would include in the category of
memory leaks in unmanaged code if it excludes bugs is beyond me... a
memory leak is a bug pretty much by definition.

In short, it's harder to have memory leaks in managed code, but far
from impossible.
 
C

Christopher Ireland

Christof said:
Look furhter down in the same article:
On the other hand, if the older datatables aren't used anymore, but simply
remain in memory because they are referenced by the dataset, then I surely
would call this a memory leak.

The article also says:
"Each time that this occurs, the amount of memory that the program is using
increases. The memory does not decrease until the end of the program or the
release of the objects from the collection. When you watch the program on a
performance monitor, this appears to be a memory leak, but it is not. The
program still has control over the memory but has chosen not to release it.
The fact that the program still has control prevents this from being a
memory leak, but the fact that the program keeps increasing the amount of
memory used can make it appear to be a memory leak. "

This suggests to me that a memory leak is only a memory leak when the
program loses control over the memory. As far as I understand, in a managed
environment this never happens (except in the case of a bug in the managed
environment itself).

This does not excuse, however, badly designed managed code which keep
objects alive unnecessarily and which gives the *appearance* of a memory
leak.
 
C

Christopher Ireland

Peter said:
That's what Ward was talking about.

Thank you Peter, I think that's how I understood it.
You obviously are really talking about "UNREFERENCED managed objects
that can't be garbage collected

No, I'm not.
But it seems to me that Ward made it pretty clear that's not
what he's talking about. He's talking about objects to which he
still has references, but *shouldn't*, and so they stay allocated
even though they should have been released.

AFAIK, this can only mean a bug in the GC. Please see my reply to Christof.
It's a fundamentally different way of looking at the idea of a "memory
leak", but it's pretty much the only kind of memory leak you'd have
with managed objects and is still an example of a coding error (it's
just that the references are being kept when they shouldn't be,
instead of being lost when they shouldn't be :) ).

As I mentioned to Christof, I'm not excusing badly designed managed code and
I agree that such code can give rise to the *appearance* of a memory leak.
 
C

Christopher Ireland

Jon said:
Basically what it's saying is that bugs can cause things which look
like memory leaks.

That's certainly how I understood it.
Quite what it would include in the category of
memory leaks in unmanaged code if it excludes bugs is beyond me... a
memory leak is a bug pretty much by definition.

In unmanaged code it would be a bug in your code, in managed code it would
be a bug in the GC, no?
In short, it's harder to have memory leaks in managed code, but far
from impossible.

I agree, but I think I was simply trying to say that real memory leaks in
managed code are due to bugs in the framework rather than bugs in your code
(making the distinction between bugs and badly designed code here (somehow
<g>)).
 
J

Jon Skeet [C# MVP]

Christopher Ireland said:
That's certainly how I understood it.


In unmanaged code it would be a bug in your code, in managed code it would
be a bug in the GC, no?

No - the kind of leak they're talking about is caused by a bug in your
code, by keeping a reference in another (uncollected) object.

As for bugs in the GC - a memory leak due to that would be similar to a
memory leak in MFC or a 3rd party library.
I agree, but I think I was simply trying to say that real memory leaks in
managed code are due to bugs in the framework rather than bugs in your code
(making the distinction between bugs and badly designed code here (somehow
<g>)).

If they *are* saying that, then I disagree - it's easy to assign
something to a static variable and forget about it. You'll then
potentially have what looks like a memory leak, and it would certainly
be due to a bug in your code. Not a failure to call free(), but a
failure to effectively make the object eligible for garbage collection.
 
J

Jon Skeet [C# MVP]

Christopher Ireland said:
AFAIK, this can only mean a bug in the GC. Please see my reply to Christof.

No, it doesn't mean a bug in the GC. It almost certainly means a bug in
Ward's code, where he's got a reference to an object even though his
design (or whatever) says that he shouldn't. I believe he's trying to
track down that bug. Read Peter's sentence very carefully:

<quote>
He's talking about objects to which he still has references, but
*shouldn't*, and so they stay allocated even though they should have
been released.
</quote>

If he still has references to the object, it shouldn't be garbage
collected, so it can't be a GC bug.
As I mentioned to Christof, I'm not excusing badly designed managed
code and I agree that such code can give rise to the *appearance* of
a memory leak.

And that's the situation I believe Ward is in.
 
J

Jon Skeet [C# MVP]

This suggests to me that a memory leak is only a memory leak when the
program loses control over the memory. As far as I understand, in a managed
environment this never happens (except in the case of a bug in the managed
environment itself).

That seems like a fairly arbitrary definition of "memory leak" to me (I
know it's not yours) and not a terribly useful one. I find the
wikipedia statement clearer:

<quote>
In computer science, a memory leak is a particular kind of
unintentional memory consumption by a computer program where the
program fails to release memory when no longer needed.
</quote>

Certainly a *user* couldn't care less whether their memory is being
eaten due to references that are still available or due to memory which
no code knows about - and it doesn't make huge odds when it comes to
debugging, either.
 

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

Top