Is There a Time at which to ignore IDisposable.Dispose? - c#

Certainly we should call Dispose() on IDisposable objects as soon as we don't need them (which is often merely the scope of a "using" statement). If we don't take that precaution then bad things, from subtle to show-stopping, might happen.
But what about "the last moment" before process termination? If your IDisposables have not been explicitly disposed by that point in time, isn't it true that it no longer matters? I ask because unmanaged resources, beneath the CLR, are represented by kernel objects - and the win32 process termination will free all unmanaged resources / kernel objects anyway. Said differently, no resources will remain "leaked" after the process terminates (regardless if Dispose() was called on lingering IDisposables).
Can anyone think of a case where process termination would still leave a leaked resource, simply because Dispose() was not explicitly called on one or more IDisposables?
Please do not misunderstand this question: I am not trying to justify ignoring IDisposables. The question is just technical-theoretical.
EDIT: And what about mono running on Linux? Is process termination there just as "reliable" at cleaning up unmanaged "leaks?"
LATE EDIT: Although "other uses" may exist for IDisposables, my focus is strictly on resource leaks. I've heard two answers: (1) if your process refuses to terminate, you will have a leak and (2) yes, resources can leak even if the process terminates. I certainly agree with item (1), though it is just outside the scope of what I'm after. Otherwise, item (2) is exactly what i'm looking for, but I can't shake the feeling it is just a guess. Jeffrey Richter ("Windows via C/C++") explains that a (gracefully) terminated Win32 process will not leave leaked or orphaned resources. Why would a process containing the CLR change that? Where is the documentation, specific example, or theoretical scenario that gives credance to the idea that the Win32 process cleanup capability is compromised when using the CLR?

Technically speaking, it all depends on what the IDisposable does. It has been used for a lot of things, not just unmanaged resources.
For example, when working on an Outlook application I had built a nice little abstraction of the Outlook API. Attachments were particularly annoying to work with as streams because you needed to save it out to a temp file, work with it, then clean it up.
So my abstraction looked something like this:
OutlookMailItem mailItem = blah;
using (Stream attachmentStream = mailItem.OpenAttachment("something.txt")) {
// work with stream
}
When Dispose was called on the AttachmentStream, the temp file it was based on was deleted. In this case, if Dispose was not called, the temp file would never be cleaned up. I had a process at startup to look for these orphaned files but I figured I'd present this as an example.
In reality, nearly all IDisposable implementations which wrap some kind of socket, handle, or transaction will simply be cleaned up by the operating system upon process termination. But obviously that's like welfare. Avoid it if you can.

During a cooperative shutdown, the AppDomain is unloaded, which causes all finalizers to execute:
From Object.Finalize documentation:
During shutdown of an application domain, Finalize is automatically called on objects that are not exempt from finalization, even those that are still accessible.
So you're safe on shutdown as long as two criteria are met:
Every IDisposable object that's still alive has a correctly-implemented finalizer (true of Framework classes, may not be true of less-trustworthy libraries); and
It's actually a cooperative shutdown, and not an abnormal shutdown such as a hard process termination, Ctrl-C in a console app, or Environment.FailFast.
If either of these two criteria aren't met, it is possible that your application is holding onto global unmanaged resources (such as a mutex), which actually will leak. Therefore, it's always better to call Dispose early if you can. Most of the time, you can rely on the CLR and object finalizers to do this work for you, but better to be safe than sorry.

One thing that I often find myself disposing is serial ports-- now, while a serial port should be freed when the program lets up, other programs can't access the serial port while it's being held by another process. So, if your process refuses to die, then you're tying up a serial port. That can be really bad if the user tries to restart your program, but a zombie version of the previous process is still holding on to the serial port.
And yes, I've had my program find itself in a zombie state before, and then the customer complain that the program isn't working anymore because the program fails to attach to the serial port on restart. The result is either walking the user through killing a process in the task manager or having them reboot, neither of which is a particularly user-friendly task.

You write your custom code to free objects in your disposable class. It's for you to write code to free unmanaged and managed code.
This is why we need Dispose function. All freeing up of memory is not automatic, like you said in unmanaged code's case.
Now, if you think that unmanaged code is automatically freed by OS, it's not true. There are many handles and locks that may remain active if not properly disposed by your application.

First, I would like to point out that IDisposable is not only for Windows kernel objects or unmanaged memory. Rather, it is for things that the garbage collection does not understand (of which kernel objects are a special case).
A small example, just to give you an idea:
sealed class Logger : IDisposable
{
private bool _disposed = false;
public Logger()
{
System.IO.File.AppendAllText( #"C:\mylog.txt", "LOG STARTED" );
}
~Logger()
{
Dispose();
}
public void Dispose()
{
if ( !_disposed )
{
System.IO.File.AppendAllText( #"C:\mylog.txt", "LOG STOPPED" );
_disposed = true;
}
}
public void WriteMessage( string msg )
{
System.IO.File.AppendAllText( #"C:\mylog.txt", "MESSAGE: " + msg );
}
}
Note that this Logger class does not "hold" any kernel-object-style resources. It opens file and closes it right away. However, there is this logic behind that it should write "LOG STOPPED" when the object is destroyed. This logic is something that GC cannot understand - and this is the place to use IDisposable.
Therefore, you cannot count on Windows cleaning up kernel objects after you. There might still be something even Windows doesn't know.
That being said, however, provided your disposable objects are properly written (i.e. calling Dispose in finalizer), they will still be disposed by the CLR upon process exit.
So, the answer is: yes, it is not necessary to call Dispose just before project exit. But NOT because disposable resources are kernel objects (because they're not necessarily are).
Edit
As Josh Einstein correctly pointed out, finalizers are actually not guaranteed to run on process exit. So then the answer becomes: always call Dispose, just to be sue

Related

Do I have to use a “using” statement in a short method?

Do I have to use a using statement to dispose immediately even in a method? Or will the ending of the method cause an automatic Dispose of all local variables including graphics?
(I’m asking this because I’ve seen examples that have Dispose calls at the end of methods, and wanted to know if that’s really necessary.)
Thanks.
Yes, you do. Going out of scope does not do anything; it does not call Dispose(), it does not garbage-collect, it does not call a finalizer.
If the type is IDisposable, then yes. It is your job to tidy up after yourself (assuming that the object is actually "done with" at this point).
Possible side-effects of not doing this:
files get left open and cause access-exceptions (FileStream)
connections get left open and cause pool saturation (DbConnection)
unmanaged handles get saturated and cause resource starvation (any winforms/etc)
transactions get left open and cause blocking (TransactionScope / DbTransaction)
etc
basically, bad things.
Furthermore, in most cases where you see Dispose() at the bottom of the method, a using would be preferable. There are some cases where that isn't possible (fields on an object, for example), but the point remains: it sounds like those are bad examples.
You don't ever have to dispose of an object. But if you want to release unmanaged resources earlier rather than whenever the GC gets around to it (which is when it processes the fReachable queue) then yes you should since the scope of of a method does not determine when a disposable object's finalize will be called.
For more you might want to read Jeffrey Richter's Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework
As delnan noted if there's a hard limit to the resources you're using you're much more likely to impacted if you let it get reclaimed by the GC rather than calling Dispose. DB connections are a good example of this kind of reasource and is certainly the reason why the NumberOfReclaimedConnections performance counter got created.
Yes, use using. It is a great statement.
Actually if you don't call Dispose (either manually or by using using), you can end up in a situation where your managed memory is stil quite empty, but unmanaged resources are depleted. Eventually it can cause a deadlock because other objects or other processes will wait for your unmanaged resources and you will wait for them. (Garbage collector won't run, because managed memory still won't be full.)
So please call Dispose as soon as you can. Once you don't need an object which has got that method defined, call it.

Consequences of NOT properly implementing IDisposable

I am comfortable with how to implement IDisposable..
However I'm not clear as to the exact consequences of not implementing this properly. Is it a case that unmanaged resources will never be cleared thus causing memory leaks or will the memory eventually get recycled anyway, just not in a timely manner?
It depends.
If the object in question fails to implement IDisposable, but does still implement a finalizer correctly, the resources will eventually get cleaned up.
However, if it doesn't properly implement a finalizer, AND it's wrapping an unmanaged resource, that resource will be leaked. This is more often a resource leak (ie: leaking a HANDLE stored as IntPtr) more than a traditional "memory leak" (though, of course, the object being pointed to does still use memory).
will the memory eventually get recycled anyway?
One point here... IDisposable has nothing to do with memory - it's about resources. These resources often use memory of their own, but implementing IDisposable does not cause your garbage collector to reclaim memory more quickly.
It depends entirely on what te implementation is, of course.
An incorrect dispose on a SqlTransaction could lead to excessive long blocking, for example - impacting multiple machines and users. An incorrect dispose on a SqlConnection could cause connection saturation and inability to connect. These are not just memory (etc) issues.
IIRC a missing graphic (pen/brush/whatever) dispose was responsible for a VS crash bug - GC didn't happen because there was no memory pressure, so instead it simply saturated the GDI handles and broke.
An incorrect file/stream dispose could cause exceptions due to a file bring unavailable for reading/writing - potentially losing data.
With unmanaged resources not properly handled, anything is possible.
Instead of thinking in terms of some vaguely-defined "resources", think of IDisposable as meaning "This object manipulates something outside itself (and possibly even outside the computer!) in a way that needs to be cleaned up, while the information necessary for such cleanup still exists." A finalizer which fires essentially says "Nobody else is using this stuff anymore, and I'm the only one who knows about it; I'd better clean it up because nobody else is going to."
It is dangerous to assume that finalizers will magically take care of things; while many objects can be safely abandoned, many others cannot. In some cases, it will be easy for an object to detect that it has been abandoned and clean up appropriately. In some other cases, it may be so difficult as to be impractical. Consider an object which is supposed to count how many times the word "quack" appears in a long-lived data stream. If the creator of the object has forgotten about it, and nobody is every going to query the count, the object may as well go away. Unfortunately, since the data stream holds a reference to the counting object (so as to let it know when data comes in), the counter object won't go away. If code creates a counter, then forgets about it, then creates another one, forgets about it, etc. this could become an unbounded memory leak.
A class that holds unmanaged resources should ensure that they are cleaned up during finalization. However, this only happens when the garbage collector gets around to it.
Not calling Dispose means waiting for the garbage collector to need memory before the resources are released.
The latter of the two. Just not in a timely manner.
The importance of this depends on the resources you are allocating. This is why you are more likely to see IDisposable interfaces on objects that open files and reference other, more crticital, resources.
Yes, unmanaged resources will never be released. (This assumes that the IDisposable types in question don't implement a "fallback" finaliser. If they do then the finaliser should sort things out... eventually.)
However, it's not just unmanaged memory allocations that you need to worry about; it's any unmanaged resources. For example, if you don't properly dispose of your database connections then you might find that the connection pool quickly gets exhausted.
Another potential problem with not implementing the disposable pattern properly - it is very easy to accidentally call .Dispose() more than once. If your Dispose method does not check for successive calls to it, and (eg.) attempts to free up an unmanaged resource more than once, you might end up with some unrecoverable error, or unexpected behaviour.

Using destructor/finaliser expensive?

I'm busy getting confused about non-deterministic destruction. In an answer to another question I got the advice that destructors/finalisers (which I assume are the same thing in c#, i.e. the function called ~classname()) are expensive and not required. But looking at this example a destructor is used and from the comment sounds like it may be vital. Anyone got some advice about how this all fits together and should I remove the destructor from my code?
Thanks again.
You should only include a finalizer if you absolutely have to run some cleanup at some point, whether it's performed explicitly or not. In such cases you should always have an explicit way of performing clean-up in a timely manner anyway, and that should suppress finalization anyway, so that "good" clients don't see any performance penalty.
You would normally only need a finalizer if you have a direct handle to unmanaged resources - if you only have a reference to another class which has a handle on the resource (e.g. FileStream) then you should leave it to the other class to have a finalizer.
With the advent of SafeHandle in .NET 2.0, situations where it's worth writing your own finalizer are very rare indeed.
The performance penalty of finalizers is that they make your objects live for longer than they need to: in the first GC cycle where they're otherwise considered eligible for collection, they get put on the finalizer queue - and bumped up to the next generation just like any other object which survives a GC cycle. The finalizer will then run in another thread (at some point) and only then will they be eligible to really be collected. So instead of (say) getting collected in the first gen1 collection, they live on past that until the next gen2 collection, which may be considerably later.
Usually, implementing a destructor is useful in on case: when it is not guaranteed, that client code will close all the resources(file streams, db connections and so on) properly. So, if client code will fail to do so, you will have code, which will close it, which is better than just left the resources open.
You only need the full Disposable pattern when you are dealing with an unmanaged resource directly. And then it is up to your calling code to make sure the destructor is (almost) never used.
When dealing with managed resources (= indirect ownership of unmanaged resources), the destructor is useless:
class FileWrapper
{
private FileStream fs; // managed resource
~FileWrapper()
{
if (fs != null)
fs.Dispose(); // fs is already on the GC finalizer queue
}
}
Whenever a FileWrapper object is being collected by the GC, it is certain that the fs object is in the same batch. So the call to fs.Dispose() is useless, only testing the correct (allowing multiple calls) behaviour of the FileStream.Dispose().
The only useful destructor here is the one in FileStream.

Do I need to dispose of a resource which is not actually used?

i have a stupid question, but i want to hear the community here.
So here is my code:
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
return true;
}
My question, is it any different than:
(FtpWebResponse)request.GetResponse();
return true;
Which one is better in general? which one in terms of GC and why?
The first is better, but not in terms of GC. WebResponse implements IDisposable because it has resources that need to be released such as network connections, memory streams, etc. IDisposable is in place because you, as the consumer, know when you are done with the object and you call Dispose to notify the class you're done with it, and it is free to clean up after itself.
The using pattern really just calls Dispose under the hood. E.g. your first example is actually compiled to be this:
FtpWebResponse response = (FtpWebResponse)request.GetResponse()
try
{
}
finally
{
((IDisposable)response).Dispose();
}
return true;
This is separate from the garbage collector. A class could also clean up resources in the finalizer, which gets called from GC, but you should not rely on that to happen for two reasons:
It could be a very long time before GC finally comes around, which means those resources are sitting there being consumed for no good reason.
It might not actually clean up resources in the finalizer anyway
The first one is better.
The difference is that the using statement will call dispose on the object wrapped in it. It will correctly dispose of held resources.
From MSDN, the using statement:
Provides a convenient syntax that ensures the correct use of IDisposable objects.
I appreciate that you are not interested in the response. However, the response object has been created, initialised and returned to your code whether you wanted it or not. If you don't dispose it, then it will hang around consuming resources until the GC eventually gets round to finalizing it.
I agree with what others said, but if you have such hate for the using() syntax, you could do:
((IDisposable)request.GetResponse()).Dispose();
return true;
The GC doesn't care about anything other than memory, so if you've got plenty of memory and are not consuming much of it, it might be a very long time until it does a GC. During that entire time the unmanaged resources, such as network connections, file handles, database connections, graphics handles etc., remain tied up by the objects that are waiting to be GC'd. This can cause you to run out of these resources and the GC will be oblivious because it doesn't monitor unmanaged resources.
So if you put your code in a loop and kept calling it, without calling Dispose, you might find it quickly degrades in performance(processes fighting for scarce resources) or gives you an exception due to a lack of the unmanaged resources. It depends on the context of how it is being called and how you are creating other related objects. Rather than analyze each situation, it is always safest to call Dispose as soon as you are done with the instance.
It is true that eventually Dispose will be called by the GC on an object that has gone out of scope/is no longer referenced, but this is indeterministic. Being indeterministic, you could see different results in how soon resources are free'd when testing vs production and lead to random Exceptions for failure to allocate resources when they run out. If you could choose between consistent deterministic behavior of your application and inderterministic, you'd probably want deterministic, unless maybe you are trying to confuse your Testers.

Resources that have to be manually cleaned up in C#?

What resources have to be manually cleaned up in C# and what are the consequences of not doing so?
For example, say I have the following code:
myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
// Use Brush
If I don't clean up the brush using the dispose method, I'm assuming the garbage collector frees the memory used at program termination? Is this correct?
What other resources do I need to manually clean up?
If you don't dispose something, it'll be cleaned up when the garbage collector notices that there are no more references to it in your code, which may be after some time. For something like that, it doesn't really matter, but for an open file it probably does.
In general, if something has a Dispose method, you should call it when you've finished with it, or, if you can, wrap it up in a using statement:
using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
// use myBrush
}
Handles to internal windows data structures.
Database connections.
File handles.
Network connections.
COM/OLE references.
The list goes on.
It's important to call Dispose or even better yet, use the using pattern.
using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
// use myBrush
}
If you don't dispose something, it'll be cleaned up when the garbage collector notices that there are no more references to it, which may be after some time.
In the case of System.Drawing.Brush, Windows will keep internal windows structures for the brush loaded in memory until all programs release their handle.
The consequences of not disposing your IDisposables can vary from a negligible performance hit to crashing your app.
The Brush object in your example will be cleaned up by the GC when it feels like it. But your program won't have had the benefit of that bit of extra memory you would have gained by cleaning it up earlier. If you are using a lot of Brush objects this might become significant. The GC is also more efficient at cleaning up objects if they haven't been around very long, because it is a generational garbage collector.
On the other hand, the consequences of not disposing database connection objects could mean you run out of pooled database connections very quickly and cause your app to crash.
Either use
using (new DisposableThing...
{
...
}
Or, if you need to hold on to a reference to an IDisposable in your object for its lifetime, implement IDisposable on your object and call the IDisposable's Dispose method.
class MyClass : IDisposable
{
private IDisposable disposableThing;
public void DoStuffThatRequiresHavingAReferenceToDisposableThing() { ... }
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
//etc... (see IDisposable on msdn)
}
Generally, anything that implements IDisposable should cause you to pause and research the resource you're using.
GC only happens when there's memory pressure, so you cannot predict when. Although an unload of the AppDomain will certainly trigger it.
Technically anything that inherits from IDisposable should be proactively disposed. You can use the 'using' statement to make things easier.
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
Sometimes you will see inconsistent use of IDisposable derived objects in documentation sample code as well as code that is generated by tools (i.e. visual studio).
What's nice about IDisposable is that it gives you the ability to proactively release the underlying unmanaged resource. Sometimes you really want to do this - think network connections and file resources for example.
As others have said, using is your friend.
I wrote this blog entry about how to implement IDisposable in a fairly straightforward way that is less error-prone by factoring out the parts that are the most important.
A trick I use when I can't remember whether a given object is a disposable resource is to type ".Dispose" (at most!) after the declaration to get Intellisense to check for me:
MemoryStream ms = new MemoryStream().Dispose
Then delete the .Dispose and use the using() directive:
using(MemoryStream ms = new MemoryStream())
{
...
}
Well, as long as you use the managed version of the resources and don't call the windows APIs by yourself, you should be OK. Only worry about having to delete/destroy a resource when what you get is an IntPtr, as "windows handles" (and a whole lot other things) are known in .NET, and not an object.
By the way, the resource (as any other .NET object) will be flagged for collection as soon as you leave the current context, so if you create the Brush inside a method, it will be flagged when you exit it.
If it's managed (i.e. part of the framework) you don't need to worry about it. If it implements IDisposable just wrap it in a using block.
If you want to use unmanaged resources then you need to read up on finalisers and implementing IDisposable yourself.
There's a lot more detail under this question
First upon program termination, you can assume that memory used by the process will be eliminated with the process itself.
While using dispose or destructor in.net, one must understand that the time of when the dispose function is called by the GC is non-deterministic. That why it is recommended to use the using or calling the dispose explicitly.
When using resources such as files, memory objects such as semaphors and resources that live outside of the managed world of .net must be freed.
The SolidBrush for example, you need to dispose because it is a GDI object and living outside of the .net world.
The garbage collector does not only free up at program termination, otherwise it would not be really useful (on any decent/recent OS, when the process exits, all its memory is cleaned up automatically by the OS anyway).
One of the big advantage of C# compared to C/C++ is that you don't have to care about freeing allocated objects (most of the time at least); the gc does it when the runtime decides (various strategies when/how to do it).
Many ressources are not taken care of by the gc: file, thread-related ressources (locks), network connections, etc...
One place to be careful is Objects that look small to GC but are not... In the SharePoint API for example, the SPWeb object has a small footprint as far as the GC is concerned and so will have low priority for collection, but it has really grabbed a bunch of memory (in the heap I believe) that the GC doesn't know about. You will run into some fun memory issues if you are foreaching a whole bunch of these for example, always remember to use using or dispose!
Rather than thinking of an object as "holding" resources that need to be released, it's better to think in terms of an object as having altered something (possibly outside the computer!) which will outlive it, in a way could be harmful if it not undone or "cleaned up", but which only the object can clean up. While this alteration commonly takes the form of some concrete object in a pool being marked "busy", its precise form doesn't matter. What matters is that the changes need to be undone, and the object holds information necessary to do that.
The garbage collector will handle any managed resources. In your example, the brush will be cleaned up when the garbage collector decides to, which will happen some time after the last reference to the brush is no longer valid.
There are certain things that need to be manually cleaned up, but those are pointers retrieved from unmanaged sources, such as DLL calls, nothing within the .NET Framework needs this treatment however.

Categories

Resources