Post by TomThank you Lasse Karlsen!!
I am less concerned about an error being in my code ... but still a
bit confused about understanding the inner workings of
GarbageCollection. I'm looking for a good list of the top 20 or so
most common causes of memory leaks in the C# environment.
There are two, that I can think of, major sources of memory leaks in an
application (C# or otherwise).
There's the unintentional, bug-type, memory leak where you simply forget
to deallocate memory after you're done with it. This is typically
achieved using a non-managed programming language and just forgetting to
add the appropriate code, or forgetting to call it. Typical problem is
that you return allocated memory out of a function, which the calling
code is now responsible for deallocating, but this responsibility is
both hard to ensure and hard to communicate.
The other type of memory leak, which is somewhat related, is that you
don't explicitly remove references to large data structures when you're
done with them. While you don't have to explicitly call code to free
memory allocated in a managed world, you still have to make all the
information you got about the lifetime for your data available to the
garbage collector.
A typical example of this is to have a static variable containing a list
of some sorts, and then adding large objects to that list, and then not
removing them when you're done with them, keeping the objects around
until the program closes.
Post by TomThe "Stream.Close Method" documentation states: "Closes the current
stream and releases any resources (such as sockets and file handles)
associated with the current stream."
I considered the memory a "resource" that would be freed but I have no
supporting evidence for this thought. :( The bridging between managed
and unmanaged components is certainly confusing. In my mind I thought
that if part of the component was unmanaged ... then all of it was?
Now, with your explanation, I am trying to accept that system level
buffers are also "managed" when they are created within the .Net
environment?
Memory is a resource, just not like this in this context.
Dispose/Close typically disposes of "scarce" resources, like handles,
files, sockets. Memory is not considered a scarce resource in the same
manner.
It is your responsibility to explicitly call dispose/close when you're
done with the purpose of the object, file contents, socket
communication, etc.
It is the garbage collectors responsibility to remove the memory used by
the object when you no longer have any live references to it.
Post by TomI am use to unmanaged malloc(), free(), fclose() and _fcloseall(). I
guess I should think of the .Net File.OpenRead() as a method that
creates a "partially" managed object?
You should look for the IDisposable interface. If an object implements
this interface, it typically uses a scarce resource and you should
always dispose of it when you're done with it. In the case of streams,
Close does the same as Dispose, and this is also typically true but
check the documentation just to make sure.
The IDisposable pattern also lends itself to a very easy to write
special syntax in C#:
using (FileStream stream = new FileStream(...))
{
... use the stream here
}
this translates almost directly to:
FileStream stream = new FileStream(...);
try
{
... use the stream here
}
finally
{
stream.Dispose();
}
Post by TomI wish I could find a comprehensive list of unmanaged resources used
within the .Net environment. My incomplete list only has the two items
mentioned above: 1) Sockets, 2) File handles.
As I said above, you don't need it. Instead, look for IDisposable
support, that should be all you need to know.
Off the top of my head I can add a few items though:
- anything related to GUI objects (buttons, windows, static labels,
listview, comboboxes, etc.)
- some types of image resources (cursors, icons)
- registry objects (though I'm not 100% positive here)
Post by TomI've read: (i) In a mixed managed/unmanaged solution you must manually
free unmanaged memory allocations. (ii) Usage of Stream.Close() is
required to "avoid memory leaks". -- But these two statements don't
necessarily suggest the buffer portion in a FileStream object is
either managed or unmanaged.
Stream.Close is not required to avoid memory leaks. It is needed to
close the file when you're done with it.
If you don't call Stream.Close, or Dispose, what happens is that once
you no longer have any live references to the stream, the object is
eligible for garbage collection. You're not, however, guaranteed that
this will happen any time soon. In the meantime, the file the stream
holds a reference to is open, and thus possibly locked and unavailable
to other applications, even your own should you wish to open another
stream for it.
However, once the garbage collector collects the object, the stream will
be closed correctly.
The only thing IDisposable.Dispose / Stream.Close allows you to do is
choose the time you wish to dispose of the unmanaged resources yourself.
A properly written class will do it anyway when the garbage collector
runs, but this have the consequences that unmanaged resources are held
on to and locked for a longer period of time than necessary.
Additionally there are some slight performance considerations when it
comes to just letting IDisposable objects lie around until GC picks them
up, so the rule is: IDisposable must be disposed of.
Post by TomI obviously need to read and study a lot more about .Net Memory
Management. Deeper into Yahoo I now go. For now the following *Delphi*
http://dn.codegear.com/article/28344
There are other memory managers for Delphi available that does this as
well, the methods are not directly applicable in .NET though. The JCL
class libraries comes to mind.
The two types of leaks you need to concern yourself with are:
1. Not explicitly closing streams/sockets (IDisposable) when you're done
with the objects, holding the references longer than needed
2. Holding live references to data that you no longer need, which
increases the memory usage patterns of your application
You should not have to concern yourself (much) with leaks in the sense
of unmanaged resources, unless you start mucking around with P/Invoke.
When you do, think "Here there be dragons" and find some good
information about it before diving in.
Post by TomI know zilch about Delphi and am hoping that a similar C# approach is
out there somewhere. The memory dump and tagging in the above article
is very interesting. Excellent tool and article ... just don't force
me into Delphi, please!
I would recommend GUI programming in Python before recommending Delphi
nowadays :)
--
Lasse Vågsæther Karlsen
mailto:***@vkarlsen.no
http://presentationmode.blogspot.com/
PGP KeyID: 0xBCDEA2E3