Why call Dispose()? Memory leak won't occur? - c#

Edit: My question isn't getting the main answer that I was looking for. I wasn't clear. I would really like to know two things:
Can NOT calling Dispose() cause memory leaks?
What's the worst thing that can happen if you have a large program and never call Dispose() on any of your IDisposable objects?
I was under the impression that memory leaks could occur if Dispose() isn't called on IDisposable objects.
Per the discussion on this thread, my perception was incorrect; a memory leak will NOT occur if Dispose() isn't called.
Why ever bother calling Dispose() then? Is it just to free the resource immediately, instead of sometime later? What's the worst thing that can happen if you have a large program and never call Dispose() on any of your IDisposable objects?

Dispose is used to release non-managed resources. This could mean memory, if a class allocated non-managed memory, but it is more often native objects and resources like open files and database connections.
You often need to call Dispose on a class that itself doesn't have any non-managed resources, but it does contain another class that is disposable and may have non-managed resources.
It's also sometimes useful for developers to implement dispose to ensure deterministic finalization--guaranteeing the order in which resources are freed.
Also note that classes that implement dispose often also have a finalizer to release resourcdes if Dispose is not called. Objects with a finalizer have a different life-cycle than classes without one. When they are ready for GC, the GC will see that they have a finalizer and instead of immediately collecting the object when the GC is ready to, it puts it into the finalization queue. This means that the object lives for one extra GC iteration. When you call dispose, the implementation usually (but is not required to) calls GC.SuppressFinalize() which means the finalizer no longer needs to be called.
If a class implements IDisposable, you should always call Dispose().

While some other answers seem to be suggesting that you can get away with not calling it, this is really bad advice. You should always call Dispose on any IDisposable resource.
Some .NET objects have what's called a "finalizer" - something you can define on your own classes as well, but that you rarely see done in a typical C# programmer's code. The finalizer is what runs when the garbage collector destroys the object, and sometimes it will call Dispose - but only if the implementer of the class made it that way.
The best practice is to always Dispose - no matter what. There are plenty of libraries I've used where not calling Dispose on a resource results in a memory leak, a connection leak, a operating system resource leak, or other kinds of horribleness. And the garbage collector will not reconcile the problem, because they don't implement any custom finalizer.
See related: Will the Garbage Collector call IDisposable.Dispose for me?

The convention is that if an object implements IDisposable you should call Dispose() or use the "using" pattern. The difference between Dispose() and waiting for the destructor (finalizer) to execute is that Dispose() is called right away and can be used for freeing some important resources like db connections, files, devices, unmanaged oejects, etc.
So to summarize - if it is IDisposable - Dispose() it!

Not calling Dispose will not ever (*see note 2 on wrong implementation) cause traditional "memory leak" (memory is never freed till end of the process).
The "only" thing that will happen in relation to memory is it will be freed in non-deterministic moment in the future.
One interesting case of non Dispose objects is when very small managed objects hold large amounts of unmanaged memory (i.e. allocated with some flavor of Win32 memory management functions i.e. HeapAlloc ). In this case managed memory manager may not be able to detect memory pressure properly to trigger Gen2 GC and (especially in case of x86 - 32bit process) it may prematurely fail to allocate managed memory for your process. The other issue in this case is fragmentation of address space by "waiting for GC to be de-allocated" (again mostly in x86 case) - when smaller chunks of native memory are allocated with some relatively large space between them preventing allocation of large blocks needed for managed memory management.
Notes:
This answer explicitly talks about true memory leaks/memory allocation issues cased by not disposing IDisposable object managing memory. While it is true that there are no "true memory leaks" caused by such practice most people will consider growing memory usage as memory leak (similar to storing large amount of objects in static list/dictionary for lifetime of an application).
One can create object that manages native memory and incorrectly implements IDisposable pattern. In this case it is possible to really leak native memory (irrespective of calling Dispose).
In most cases objects that implement IDisposable don't managed memory at all. For most practical C# programs native resources managed by such objects are handles for system resources like files, bitmaps, fonts, synchronization objects or COM native objects. Not disposing them in timely manner will cause other issues.
Dispose all objects properly. There is no excuse not to.

Dispose() is intended to free resources that the garbage collector won't free, such as database connections. These resources should also be freed in the finalizer, however the finalizer is much slower than the Dispose() method.

For me:
Dispose can be used in using() scope. This can help me to determine the lifespan of a IDisposeable component. I usually use this in StreamWriter/Reader or SqlConnection classes.
Another use of Dispose is it can end a lifespan of a component explicitly. Such as calling Form.Dispose() in C# winform will close the form. However, for SqlConnection, people said that just calling Dispose alone without explicitly calling Close won't guarantee the connection to be closed. Advised to call both Close and Dispose. I haven't tried this though.
And another thing, after Dispose() is called, the GC can immediaetly free the memory, because they know that the object lifespan is end, rather than waiting for the lifespan to end.
Similiar question may be C# disposing IDisposable

Can NOT calling Dispose() cause memory leaks?
Yes, of course. Below is just one example.
Assume you have a main window in your application and you create a child control that has an event subscription to the main window. You unsubscribe from them on Dispose. If you don't dispose, main window can hold the reference to your child control until you close the application.
What's the worst thing that can happen if you have a large program and
never call Dispose() on any of your IDisposable objects?
The worse case is not releasing some unwanted memory until you close the application.
And the other question is, what if you never implement IDisposable or finalization when they are required?
The worse case of having a memory leak is holding on to that memory until you restart the PC. This can happen only if you have un-managed resources and you don't implement dispose/finalize. If you implement Idisposable interface and implement the finalizer, finalization process will execute the Dispose for you.
Another reason why you should call Dispose is to Suppress the finalization.
As I've indicated before if there is any object with Finalize method and you didn't call the Dispose. That object can reside in memory for two GC cycles. In the first cycle, it enqueue that instance to the finalization queue and finalization happens after GC process. So, only next GC cycle can release that memory.

Related

Why would I force garbage collection after TCP client closed?

I am dealing with some legacy code that probably predates .NET 2. The library itself is custom asynchronous TCP communication layer used by our server.
There is a class there inheriting from System.Net.Sockets.TcpClient and the whole class hierarchy around it that implements dispose pattern and finalizers (the latter likely not needed).
My question is about suspicious line of code found in the method that handle TCP client disconnected event:
// Hack to ensure that client has disconnected
GC.Collect();
which is executed after calling methods disposing of our communication class hierarchy that eventually calls System.Net.Sockets.TcpClient Dispose method.
On a 64-bit server that can serve many clients and use gigabytes of RAM these calls can be quite expensive. I could not find anything about forcing garbage collection upon TCP client disconnection?
Two things will happen after you force GC with GC.Collect().
Memory used by unreachable objects that don't have finalizers will be reclaimed.
Objects that implement finalizers will be placed on finalizer queue, and the finalizers will be executed soon.
The comment suggests that GC.Collect() is not called to reclaim memory, but rather to execute finalizers to dispose unmanaged resources.
If IDisposable is used correctly, there is no need to rely on finalizers. Probably there are some IDisposable objects that are not Disposed correctly. You'll have to find them. One way to do it is to examine what finalizers are executed. Some memory profilers can also track such objects (for example .NET memory profiler's Dispose Tracker).

If an object has been disposed, does suppressing the gc finalizer save it some time?

Garbage Collection can become a time consuming process. In this regard, the GC tends to work only when it has to. If an object has been disposed, to help save time and aid the GC, should the GC's finalizer be suppressed?
using(var sO = new someObject())
{
//work with object
}
public class someObject : IDisposable
{
internal Stream someResource;
internal Context someContext;
public void Dispose()
{
someContext.Dispose();
someResource.Dispose();
//A: does suppressing the GC finalizer here save time for the GC?
//B: can this cause memory leaks?
//GC.SuppressFinalize(this);
}
}
To clear up some confusion:
You only need a finalizer if you need to clean up unmanaged resources in some special way.
If you have no unmanaged resources, then you don't need a finalizer.
If you have a finalizer, then you should definitely implement IDisposable.
If you have a finalizer, then you should call GC.SuppressFinalize in Dispose, because the finalizer doesn't need to be called if you've already cleaned up after yourself.
You only need to call GC.SuppressFinalize if you have a finalizer. If you don't, you probably still want to call it anyway as a defensive measure.
does suppressing the GC finalizer here save time for the GC?
If there are unmanaged resources and your object has a finalizer, then yes; your object might live a long time on the finalization queue if you don't suppress this. The resources you dispose of may also take a long time to finalize (closing an expensive I/O channel, for example).
If you don't have a finalizer, you're saying that you don't have anything unmanaged to clean up. You should still call SuppressFinalize anyway as a defensive measure.
From the FxCop rules:
"Failure to suppress finalization degrades performance and provides no benefits."
For your other question,
can this cause memory leaks?
In this example, yes, if any of the resources are unmanaged. If your object is terminated in some unusual way before it has a chance to invoke Dispose, unmanaged resources won't be properly freed. Consider what happens if someResource is unmanaged and throws an exception while you're using a someObject instance, for example.
If your object holds onto unmanaged resources and you need to guarantee those resources are cleaned up, you need a finalizer too (which would be named ~someObject in your case).
If you actively Dispose an object then yes you should suppress the finalization. There is no need for the object to be finalized if you actively / deterministically release all of the resources. Letting it hang around for the finalizer is just wasting time later on.
One point not yet mentioned: an object need only be considered "live" if there is some execution path via which code might need to access its fields or its object header (a data structure that holds information about the object's type, whether it's been used as a monitor lock, etc.) If an object field holds an unmanaged handle and the last thing the Dispose method does is to close the handle, it's possible that the object may become eligible for finalization while the Dispose method is running. Oops. Not only will the call to GC.SuppressFinalize serve to prevent the finalizer from getting enqueued after it executes; its placement as the last thing Dispose does will prevent the object from becoming eligible for finalization before it executes.

IDisposable implementation - What should go in 'if (disposing)'

I have been fixing some memory leak issues in a winforms application and noticed some disposable objects that are not Disposed explicitly (developer hasn't called Dispose method). Implementation of Finalize method also doesn't help because it doesn't go in if (disposing) clause. All the static event unregistering and collection clearing have been put in if (disposing) clause. The best practice is calling the Dispose if the object is disposable, but unfortunately this happens sometimes
If there are unmanaged objects, static event handlers and some managed collections that needs to clear when disposing. What's the way to decide what should go in and what should go out of if (disposing) clause.
Dispose method.
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
disposed = true;
}
}
It says managed objects should in if (disposing) which executes normally only when explicitly call Dispose method by the developer. If the Finalize method has been implemented and developer forgets to call the Dispose method the execution that comes here through the Finalizer does not go in if (disposing) section.
Below are my questions.
If I have static event handlers that causes memory leaks where should I un-register them? In or out of if (disposing) clause?
If I have some collections that causes memory leaks where should I clear them? In or out of if (disposing) clause?
If I am using third party disposable objects (eg: devExpress winform controls) that I am not sure whether they are managed or unmanaged objects. Let's say I want to dispose them when disposing a form. How can I know what are managed and what are non-managed objects? Being disposable doesn't say that? In such cases how to decide what should go in and what should go out of if (disposing) clause?
If I am not sure something managed or unmanaged what can be the bad consequences of disposing/clearing/unregistering-events out of the if (disposing) clause? Let's say it checks for null before disposing?
Edit
What I mean as event un-registering is something like below. Publisher is a long lived instance and below line is in the subscriber's constructor. In this case subscriber need to unregister the event and dispose before the publisher.
publisher.DoSomeEvent += subscriber.DoSomething;
Broadly, managed resources are disposed inside if (disposing) and unmanaged resources outside of it. The dispose pattern works as such:
if (disposed) {
If this object is already disposed, don't dispose of it a second time.
if (disposing) {
If disposal was requested programatically (true), dispose of managed resources (IDisposable objects) owned by this object.
If disposal was caused by the garbage collector (false), do not dispose of managed resources because the garbage collector may have already disposed of the owned managed resources, and will definitelty dispose of them before the application terminates.
}
Dispose of unmanaged resources and release all references to them. Step 1 ensures this only happens once.
disposed = true
Flag this object as disposed to prevent repeated disposal. Repeated disposal may cause a NullReferenceException at step 2 or 3.
Question 1
Don't dispose of them in the Dispose method at all. What would happen if you disposed of multiple instances of the class? You'd dispose the static members each time, despite them already being disposed. The solution I found was to handle the AppDomain.DomainUnloaded event and perform static disposal there.
Question 2
It all depends if the items of the collection are managed or unmanaged. It's probably worth creating managed wrappers that implement IDisposable for any unmanaged classes you are using, ensuring all objects are managed.
Question 3
IDisposable is a managed interface. If a class implements IDisposable, it's a managed class. Dispose of managed objects inside if (disposing). If it doesn't implement IDisposable, it is either managed and does not require disposing, or is unmanaged and should be disposed outside of if (disposing).
Question 4
If the application terminates unexpectedly, or doesn't use manual disposal, the garbage collector disposes of all objects in random order. The child object may be disposed before it's parent is disposed, causing the child to be disposed a second time by the parent. Most managed objects can safely be disposed multiple times, but only if they've been built correctly. You risk (though, unlikely) causing the gargabe collection to fail if an object is disposed multiple times.
The key to remember here is the purpose of IDisposable. It's job is to help you deterministically release resources that your code is holding, before the object is garbage collected. This is actually why the C# language team chose the keyword using, as the brackets determine the scope that the object and it's resources are required for by the application.
For instance, if you open a connection to a database, you want to release that connection and close it ASAP after you have finished with it, rather than waiting for the next garbage collection. This is where and why you implement a Disposer.
The second scenario is to assist with unmanaged code. Effectively this is anything to do with C++/C API calls to the operating system, in which case you are responsible for ensuring that the code isn't leaked. As much of .Net is written to simply P/Invoke down to the existing Win32 API this scenario is quite common. Any object which encapsulates a resource from the operating system (e.g. a Mutex) will implement a Disposer to allow you to safely and deterministically release it's resources.
However these APIs will also implement a destructor, to guarantee that if you don't use the resource correctly that it will not be leaked by the operating system. When your finalizer is called, you do not know whether or not other objects you were referencing have already been garbage collected, which is why it is not safe to make function calls upon them (as they could throw NullReferenceException), only the unmanaged references (which by definition cannot be garbage collected) will be available to the finalizer.
Hope that helps a bit.
If I have static event handlers that causes memory leaks where should I un-register them? In or out of if (disposing) clause?
Dispose method is called on instances where as static event handler are used at class level. So you should not un-register them at all in dispose. Usually static event handler should be un-register when class is unloading or at some point during the execution of application you derive that this event handler is no more required.
For all manages and un-managed resources better implement IDisposable pattern.
See here
http://msdn.microsoft.com/en-us/library/fs2xkftw%28VS.80%29.aspx
and
Finalize/Dispose pattern in C#
It sounds like you mainly have managed objects, i.e. objects that implement IDisposable. Unmanaged code would be things like IntPtr's or handles, which would normally mean calling unmanaged code or P/Invoke to get to them.
As Maheep pointed out, Dispose is not meant for this. When an object is done receiving events it should unregister itself. If that's not possible, consider using WeakReferences instead.
This probably shouldn't go in dispose unless these collections contain objects that need to be disposed. If they are disposable objects then it should go in the "if disposing" block and you should call dispose on each item in the collection.
If it implements IDisposable it's managed
You shouldn't access other managed code objects when called by the finalizer which is what being outside the "if (disposing)" block means.
Unless the sole purpose of a class is to encapsulate some resource(*) which needs to be cleaned up if abandoned, it shouldn't have a finalizer, and Dispose(bool) should never be called with a value of False, but calling Dispose(False) should have no effect. If an inherited class would need to hold a resource requiring cleanup if abandoned, it should encapsulate that resource into an object devoted solely to that purpose. That way, if the main object gets abandoned and nobody else holds any reference to the object encapsulating the resource, that object can perform its cleanup without having to keep the main object alive for an extra GC cycle.
Incidentally, I dislike Microsoft's handling of the Disposed flag. I would suggest that the non-virtual Dispose method should use an integer flag with Interlocked.Exchange, to ensure that calling Dispose from multiple threads will only result in the dispose logic being performed once. The flag itself may be private, but there should be a protected and/or public Disposed property to avoid requiring every derived class to implement its own disposal flag.
(*) A resource isn't some particular type of entity, but rather a loose term that encompasses anything a class may have asked some outside entity to do on its behalf, which that outside entity needs to be told to stop doing. Most typically, the outside entity will have granted the class exclusive use of something (be it an area of memory, a lock, a GDI handle, a file, a socket, a USB device, or whatever), but in some cases the outside entity may have been asked to affirmatively do something (e.g. run an event handler every time something happens) or hold something (e.g. a thread-static object reference). An "unmanaged" resource is one which will not be cleaned up if abandoned.
BTW, note that while Microsoft may have intended that objects which encapsulate unmanaged resources should clean them up if abandoned, there are some types of resources for which that really isn't practical. Consider an object that stores an object reference in a thread-static field, for example, and blanks out that object reference when it is Dispose'd (the disposal would, naturally, have to occur on the thread where the object was created). If the object gets abandoned but the thread still exists (e.g. in the threadpool), the target of the thread-static reference could easily be kept alive indefinitely. Even if there aren't any references to the abandoned object so its Finalize() method runs, it would be difficult for the abandoned object to locate and destroy the thread-static reference sitting in some thread.
What should go in 'if (disposing)'
All Managed objects should go inside if(disposing) clause. Managed objects should not go out side of it (which will be executed through the finalization).
The reason is that Garbage collectors finalization process can execute the Dispose(false) if that class has a Destructor. Normally there is a Destructor only if there are unmanaged resources.Garbage collector's finalization doesn't have a particular order to execute the Finalize method. So, other managed objects may not be in memory by the time finalization occurs.

Specific questions about C# Dispose Pattern

I have a few basic questions about the Dispose Pattern in C#.
In the following code snippet, which seems to be a standard way of implementing the dispose pattern, you’ll notice that managed resources are not handled if disposing is false. How/when are they handled? Does the GC come along and handle the managed resources later? But if that’s the case, what does the GG.SuppressFinalize(this) call do? Can someone give me an example of disposing of managed resources? Unhooking events comes to mind. Anything else? The way the pattern is written, it seems they would get disposed (later) if you did nothing in the “if (disposing)” section. Comments?
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Dispose managed resources.
}
// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
}
disposed = true;
// If it is available, make the call to the
// base class's Dispose(Boolean) method
base.Dispose(disposing);
}
// implements IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
Is it true what I read about locks in Dispose(bool) in this thread, How do I implement the dispose pattern in c# when wrapping an Interop COM Object?? It says, “Meta-meta comment - as well as that, it's important that you never acquire locks or use locking during your unmanaged cleanup.” Why is that? Does it apply to unmanaged resources as well?
Finally, does on ever implement a finalizer (~MyClass() in C#) without implementing IDisposable? I believe I read somewhere that finalizers and IDisposable are not necessary (or desirable) if there are no unmanaged resources. However, I do see the use of a finalizer without IDisposable in some examples (see: http://www.codeproject.com/KB/cs/idisposable.aspx as one example)
Thanks,
Dave
This way of implementing the IDisposable pattern is a fail-safe way: In case a client forgets to call Dispose, the finalizer called by the runtime will call Dispose(false) later (Note that this part is missing in your sample).
In the latter case, i.e. when Dispose is called by the finalizer, managed resources will already have been cleaned up because otherwise the object in question would not have been eligible for garbage collection.
But if that’s the case, what does the GC.SuppressFinalize(this) call do?
Running the finalizer comes with additional costs. Therefore it should be avoided if possible. Calling GC.SuppressFinalize(this) will skip running the finalizer and therefore the object can be garbage collected more efficiently.
In general one should avoid relying on finalizers as there is no guarantee that a finalizer will run. Some of the problems with finalizers are described by Raymond Chen in the following post:
When do I need to use GC.KeepAlive?
Nobody got to the last two questions (btw: ask only one per thread). Using a lock in Dispose() is pretty lethal to the finalizer thread. There's no upper-bound on how long the lock might be held, your program will crash after two seconds when the CLR notices that the finalizer thread got stuck. Moreover, it is just a bug. You should never call Dispose() when another thread might still have a reference to the object.
Yes, implementing a finalizer without implementing IDisposable is not unheard of. Any COM object wrapper (RCW) does that. So does the Thread class. This was done because it just isn't practical to call Dispose(). In the case of a COM wrapper because it is just not possible to keep track of all reference counts. In case of Thread because having to Join() the thread so that you could call Dispose() defeats the purpose of having a thread.
Pay attention to Jon Hanna's post. Implementing your own finalizer is indeed wrong 99.99% of the time. You've got the SafeHandle classes to wrap unmanaged resources. You'd need something pretty obscure to not be wrappable by them.
The pattern described above was a matter of dealing eloquently with the overlapping concerns of disposal and finalisation.
When we are disposing, we want to:
Dispose all disposable member objects.
Dispose the base object.
Release unmanaged resources.
When finalising we want to:
Release unmanaged resources.
Added to this are the following concerns:
Disposal should be safe to call multiple times. It should not be an error to call x.Dispose();x.Dispose();
Finalisation adds a burden to garbage collection. If we avoid it if we can, specifically if we have already released unmanaged resources, we want to suppress finalisation as it is no longer needed.
Accessing finalised objects is fraught. If an object is being finalised, then any finalisable members (which would also be dealing with the same concerns as our class) may or may not have already been finalised and will certainly be on the finalisation queue. As these objects will likely also be managed disposable objects, and as disposing them will release their unmanaged resources, we do not want to dispose of them in such a case.
The code you give will (once you add in the finaliser that calls Dispose(false) manage these concerns. In the case of Dispose() being called it will clean up both managed and unmanaged members and suppress finalisation, while also guarding against multiple calls (it is not however thread-safe in this regard). In the case of the finaliser being called, it will clean up unmanaged members.
However, this pattern is only required by the anti-pattern of combining managed and unmanaged concerns in the same class. A much better approach is to handle all unmanaged resources through a class which is concerned only with that resource, whether SafeHandle or a separate class of your own. Then you will have one of two patterns, of which the latter will be rare:
public class HasManagedMembers : IDisposable
{
/* more stuff here */
public void Dispose()
{
//if really necessary, block multiple calls by storing a boolean, but generally this won't be needed.
someMember.Dispose(); /*etc.*/
}
}
This has no finaliser and doesn't need one.
public class HasUnmanagedResource : IDisposable
{
IntPtr _someRawHandle;
/* real code using _someRawHandle*/
private void CleanUp()
{
/* code to clean up the handle */
}
public void Dispose()
{
CleanUp();
GC.SuppressFinalize(this);
}
~HasUnmanagedResource()
{
CleanUp();
}
}
This version, which will be much rarer (not even happening in most projects) has the disposal deal solely with dealing with the sole unmanaged resource, for which the class is a wrapper, and the finaliser doing the same if disposal didn't happen.
Since SafeHandle allows for the second pattern to be handled for you, you shouldn't really need it at all. In any case, the first example I give will handle the vast majority of cases where you need to implement IDisposable. The pattern given in your example should only be used for backwards compatibility, such as when you derive from a class that uses it.
...you’ll notice that managed resources are not handled if disposing is false. How/when are they handled?
You didn't include it in your sample, but often the type will have a destructor which will call Dispose(false). Thus, when disposing is false, you "know" that you're in a finalizer call, and thus should *not* access any managed resources, because they might have already been finalized.
The GC finalization process only ensures that finalizers are invoked, not the order that they're invoked in.
what does the GG.SuppressFinalize(this) call do?
It prevents the GC from adding your object to the finalization queue and eventually calling object.Finalize() (i.e. your destructor). It's a performance optimization, nothing more.
The way the pattern is written, it seems they would get disposed (later) if you did nothing in the “if (disposing)” section
Maybe; it depends upon how the type is written. A major point to the IDisposable idiom is for "deterministic finalizaion" -- saying "I want your resources freed now" and having it mean something. If you "ignore" the disposing=true block and don't "forward" the Dispose() call, one of two things will happen:
If the type has a finalizer, the finalizer for the object may eventually be invoked sometime "later".
If the type doesn't have a finalizer, the managed resource will "leak," as Dispose() will never be invoked on them.
it's important that you never acquire locks or use locking during your unmanaged cleanup.” Why is that? Does it apply to unmanaged resources as well?
It's a sanity issue -- YOUR sanity. The simpler your cleanup code, the better, and it's always a good idea to not throw exceptions from Dispose(). Using locks can result in exceptions or deadlocks, either of which are good ways to ruin your day. :-)
does on ever implement a finalizer (~MyClass() in C#) without implementing IDisposable
One could, but it would be considered bad style.
The normal way for objects to be disposed is by calling it's Dispose() method. When done that way, the SuppressFinalize call removes the object from the finalizer queue, turning it into a regular managed object that can easily be garbage collected.
The finalizer is only used when the code fails to dispose the object properly. Then the finalizer calls Dispose(false) so that the object can at least try to clean up unmanaged resources. As any managed objects that the object references may already have been garbage collected at this stage, the object should not try to clean up them.
Instead of trying to learn about disposition via the pattern, you might want to flip things around and try learning why the pattern is implemented this way based on CLR fundamentals and the intended usage of the IDisposable interface. There's a very good introduction to this that should answer all your questions (and a few you didn't think to ask) at http://msdn.microsoft.com/en-us/magazine/cc163392.aspx.
If your class will hold unmanaged resources directly, or if it might ever be inherited by a descendant class that will do so, Microsoft's dispose pattern will provide a good way to tie together the finalizer and disposer. If there's no realistic possibility that either your class or its descendants will ever hold unmanaged resources directly, you should delete the template code and simply implement Dispose directly. Given that Microsoft has strongly recommended that unmanaged resources be wrapped in classes whose sole purpose is to hold them(*) (and has classes like SafeHandle for precisely that purpose) there's really no need for the template code anymore.
(*) Garbage collection in .net is a multi-step process; first the system determines which objects aren't referenced anywhere; then it makes a list of Finalize'able objects which aren't referenced anywhere. The list, and all objects on it, will be re-declared "live", which will mean all objects referred to by them will also be live. At that point, the system will perform an actual garbage collection; it then will run all the finalizers on the list. If an object holds, e.g. a direct handle to a font resource (unmanaged) as well as references to ten other objects which in turn hold direct or indirect references to a hundred more objects, then because of the unmanaged resource the object will need a finalizer. When the object comes due for collection, neither it nor the 100+ objects to which it holds direct or indirect references will be eligible for collection until the pass after its finalizer runs.
If instead of holding a direct handle to the font resource, the object held a reference to an object which holds the font resource (and nothing else), the latter object would need a finalizer, but the former one would not (since it doesn't hold a direct reference to the unmanaged resource. Only one object (the one which held the finalizer), rather than 100+, would have to survive the first garbage collection.

Garbage collection Guarantees

What guarantees are the for the garbage collector?
From my research I have managed to find:
If there is still a reference to the memory it will not be garbage collected
If there is no reference:
When it is GC is non deterministic
When the GC kicks in the finalizer will be run before memory is released.
There is no guarantee about the order of Finalizers (so do not assume parent will be run before child).
But what I really want to know is:
Is there a guarantee that all memory will eventually be garbage collected and the finalizer (destructor) run on the object (assuming the program exited nicely). For example an application with no memory pressure when it eventually exits will it force the GC to go find all objects and make sure the finalizer (destructor) is called (including static member variables)?
I did find a quote on this page:
http://www.c-sharpcorner.com/UploadFile/tkagarwal/MemoryManagementInNet11232005064832AM/MemoryManagementInNet.aspx
In addition, by default, Finalize methods are not called for unreachable objects when an application exits so that the application may terminate quickly.
But I am not sure how authoritative this quote is.
I also found documentation on:
CriticalFinalizerObject
Is there a guarantee that all memory
will eventually be garbage collected
and the finalizer (destructor) run on
the object (assuming the program
exited nicely).
No. From the Object.Finalize documentation it is clear that finalizers may not be invoked if
Some other finalizers don't finish properly:
Another finalizer blocks indefinitely
(goes into an infinite loop, tries to
obtain a lock it can never obtain and
so on). Because the runtime attempts
to run finalizers to completion, other
finalizers might not be called if a
finalizer blocks indefinitely.
Some other finalizers create more
finalizable objects, making it
impossible to finalize all
finalizable objects:
The runtime continues to Finalize
objects during shutdown only while the
number of finalizable objects
continues to decrease.
Some other finalizers throw exceptions:
If Finalize or an override of Finalize
throws an exception, and the runtime
is not hosted by an application that
overrides the default policy, the
runtime terminates the process and no
active try-finally blocks or
finalizers are executed. This behavior
ensures process integrity if the
finalizer cannot free or destroy
resources.
That being said, there are more reasons why you wouldn't want to use finalizers unless strictly necessary.
They slow down the garbage collector
(even making it possible to slow it
down so much that memory is not
reclaimed as fast as it is used up).
They run on another thread, bringing
multi-threading issues into play.
They're not executed in a
deterministic order.
They can resurrect objects which were
already finalized (and which won't be
finalized again unless explicitly
re-registered for finalization).
The only time you should write a finalizer is when you are building a type to handle a new kind of unmanaged resource. For example, a data access layer that uses Sql Server in a business app doesn't need a finalizer anywhere, even though there are unmanaged database connections involved, because the basic SqlConnection class will already finalize those connections if needed. But if you're building a brand new database engine from scratch that has connection limits similar to sql server's and are implementing the ado.net provider for it, that connection type should implement a finalizer to be as sure as possible that your connections are released.
But you don't get any guarantees beyond what happens when a process ends.
Update:
Given this context:
I am having a discussion with a collegue over a code review I did of his code. He insists that the destructor is guranteed to be called on an object. I disagree (but am not sure) and would prefer the use of IDisposable.
You are right to criticize the use of a destructor/finalizer. As I said above, you should only use them when working with an unmanaged resource that is genuinely new. Not just that instance of the resource, but the kind of resource you are working with.
For code that wraps "normal" unmanaged resources (things like SqlConnection, TcpClient, etc), IDisposable is a better choice. Then you know the resource will be cleaned up as soon as Dispose() is called rather than needing to wait for the type to be collected. If no one calls Dispose() (which is likely your colleague's concern), by the time your new type can be collected the instance of the original type for the unmanaged resource you are wrapping should be able to be collected as well, and it's finalizer will release the resource.
The main thing you need to bring to the table is that the finalizer cannot be called until the object is collected. You have to wait on the garbage collector, meaning you may be holding the resource open even longer. IDisposable allows you to release it right away. Of course you could do both, but that doesn't sound like what's going on here, and if you do have both you have to be careful not to conflict with the original type's finalizer or you could cause unwanted and harmful exceptions. And really, your own finalizer implementation is just redundant here and adds needless complexity.
Finally, I have to take issue with this statement:
If there is still a reference to the memory it will not be garbage collected
There can be references to an object and it will still be collected. What matters is if the object is reachable: are any of the references to the object rooted. For example, you may have a list with several objects in it. The list goes out of scope. Obviously there is still a reference to all of the objects in the list, but they can still all be collected in the first pass of the GC because the reference is no longer rooted.
1.6.7.6 of the Spec says:
1.6.7.6 Destructors
A destructor is a member that implements the actions
required to destruct an instance of a
class. Destructors cannot have
parameters, they cannot have
accessibility modifiers, and they
cannot be invoked explicitly. The
destructor for an instance is invoked
automatically during garbage
collection.
The garbage collector is
allowed wide latitude in deciding when
to collect objects and run
destructors. Specifically, the timing
of destructor invocations is not
deterministic, and destructors may be
executed on any thread. For these and
other reasons, classes should
implement destructors only when no
other solutions are feasible.
The
using statement provides a better
approach to object destruction.
So no, it's not guaranteed they are called.
The only time that a finalizer won't be invoked at all is if an AppDomain is forcibly unloaded.
In general, you don't need to worry about it.
There is no guarantee.
There might be a guarantee if your process terminates nicely for some definition of nicely. But there are so many things not nice that can happen:
power failure
process terminated in a 'hard' or 'forced' way
unmanaged thread throwing calling OS exit() function or throwing an exception
call to System.Environment.FailFast, which does:
MSDN: "Terminates a process but does not execute any active try-finally blocks or finalizers."

Categories

Resources