Ignoring unsafe code, .NET cannot have memory leaks. I\'ve read this endlessly from many experts and I believe it. However, I do not understand why this is so.
It is
Here's an example of a memory leak in .NET, which doesn't involve unsafe/pinvoke and doesn't even involve event handlers.
Suppose you're writing a background service that receives a series of messages over a network and processes them. So you create a class to hold them.
class Message
{
public Message(int id, string text) { MessageId = id; Text = text; }
public int MessageId { get; private set; }
public string Text { get; private set; }
}
OK, so far so good. Later on you realize that some requirement in the system could sure be made easier if you had a reference to the previous message available when you do the processing. There could be any number of reasons for wanting this.
So you add a new property...
class Message
{
...
public Message PreviousMessage { get; private set; }
...
}
And you write the code to set it. And, of course, somewhere in the main loop you have to have a variable to keep up with the last message:
Message lastMessageReceived;
Then you discover some days later than your service has bombed, because it has filled up all the available memory with a long chain of obsolete messages.
I suppose it is possible to write software, e.g. the .NET runtime environment (the CLR), that does not leak memory if one is careful enough. But since Microsoft does issue updates to the .NET framework via Windows Update from time to time, I'm fairly sure that there are occasional bugs even in the CLR.
All software can leak memory.
But as others have already pointed out, there are other kinds of memory leaks. While the garbage collector takes care of "classic" memory leaks, there's still, for example, the problem of freeing so-called unmanaged resources (such as database connections, open files, GUI elements, etc.). That's where the IDisposable
interface comes in.
Also, I've recently come across with a possible leaking of memory in a .NET-COM interop setting. COM components use reference counts to decide when they can be freed. .NET adds yet another reference counting mechanism to this which can be influenced via the static System.Runtime.InteropServices.Marshal
class.
After all, you still need to be careful about resource management, even in a .NET program.
You can absolutely have memory leaks in .NET code. Some objects will, in some cases, root themselves (though these are typically IDisposable
). Failing to call Dispose()
on an object in this case will absolutely cause a real, C/C++ style memory leak with an allocated object that you have no way to reference.
In some cases, certain timer classes can have this behavior, as one example.
Any case where you have an asynchronous operation that may reschedule itself, you have a potential leak. The async op will typically root the callback object, preventing a collection. During execution, the object is rooted by the executing thread, and then the newly-scheduled operation re-roots the object.
Here's some sample code using System.Threading.Timer
.
public class Test
{
static public int Main(string[] args)
{
MakeFoo();
GC.Collect();
GC.Collect();
GC.Collect();
System.Console.ReadKey();
return 0;
}
private static void MakeFoo()
{
Leaker l = new Leaker();
}
}
internal class Leaker
{
private Timer t;
public Leaker()
{
t = new Timer(callback);
t.Change(1000, 0);
}
private void callback(object state)
{
System.Console.WriteLine("Still alive!");
t.Change(1000, 0);
}
}
Much like GlaDOS, the Leaker
object will be indefinitely "still alive" - yet, there is no way to access the object (except internally, and how can the object know when it's not referenced anymore?)
Here are other memory leaks that this guy found using ANTS .NET Profiler: http://www.simple-talk.com/dotnet/.net-tools/tracing-memory-leaks-in-.net-applications-with-ants-profiler/
After reviewing Microsoft documentation, specifically "Identifying Memory Leaks in the CLR", Microsoft does make the statement that as long as you are not implementing unsafe code within your application that it is not possible to have a memory leak
Now, they also point out the concept of a perceived memory leak, or as was pointed out in the comments a "resource leak", which is the use of an object that has lingering references and is not disposed of properly. This can happen with IO Objects, DataSets, GUI elements, and the like. They are what I would typically equate to a "memory leak" when working with .NET, but they are not leaks in the traditional sense.
Due to garbage collection, you can't have regular memory leaks (aside from special cases such as unsafe code and P/Invoke). However, you can certainly unintentionally keep a reference alive forever, which effectively leaks memory.
edit
The best example I've seen so far of a genuine leak is the event handler += mistake.
edit
See below for an explanation of the mistake, and of the conditions under which it qualifies as a genuine leak as opposed to an almost-genuine leak.