Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which objects does the garbage collector not clean up?

A static analysis tool keeps telling me that my C# code has resource leaks in it.

Here's an example:

StringReader reader = new StringReader(...); 

// do something with reader

...

} // static analysis tool cries that I've leaked **reader**

Is my tool correct? If so, why?

Edit (replying to comment) - My static analysis tool says that I've got a bunch of resource leaks. I know from this forum that certain Java AWT objects need to be explicitly freed, otherwise a leak occurs. Are there C# objects that need to be explicitly freed?

like image 531
Kevin Meredith Avatar asked Nov 23 '10 21:11

Kevin Meredith


2 Answers

Yeah, your code is leaking badly. It should be like this:

using (StringReader reader = new StringReader(...))
{

}

Every class that implements IDisposable needs to be wrapped in a using block to ensure that the Dispose method is always called.


UPDATE:

Elaborating: in .NET there's the IDisposable interface which defines the Dispose method. Classes that implement this interface (like files streams, database connections, readers, ...) might contain pointers to unmanaged resources and the only way to ensure that those unmanaged resources/handles are freed is to call the Dispose method. So in .NET to ensure that some code is called even if an exception is thrown is to use a try/finally statement:

var myRes = new MyResource(); // where MyResource implements IDisposable
try
{
    myRes.DoSomething(); // this might throw an exception
}
finally
{
    if (myRes != null)
    {
        ((IDisposable)myRes).Dispose();
    }
}

People writing C# code have quickly realized that writing this every time you was dealing with a disposable resource was a PITA. So they've introduced the using statement:

using (var myRes = new MyResource())
{
    myRes.DoSomething(); // this might throw an exception
}

which is kinda shorter.

like image 86
Darin Dimitrov Avatar answered Oct 04 '22 01:10

Darin Dimitrov


Your code isn't actually leaking anything in this specific case, because StringReader doesn't really have any resources to clean up, just like MemoryStream doesn't. (With MemoryStream you can still end up needing to dispose of it if you're using it asynchronously or remoting it... but in straightforward cases it doesn't matter.)

However, it's a good idea to dispose of anything which implements IDisposable just on principle. This will avoid you leaking (perhaps temporarily) unmanaged resources such as file handles.

For example, suppose you changed your code to:

StreamReader reader = new StreamReader("file.txt");
...

If you don't close or dispose reader here (in a finally block or via a using statement) it will hold the file open until whatever type is directly holding the OS file handle is finalized. Disposing of things explicitly not only frees unmanaged resources earlier - it also takes finalizable objects off the finalization queue, which means they can be garbage collected earlier.

like image 20
Jon Skeet Avatar answered Oct 03 '22 23:10

Jon Skeet