Reputation: 16979
Will an IDisposable memory leak if you don't use a using statement?
And if so, can someone provide a memory leak example if its not much code?
Upvotes: 3
Views: 1369
Reputation:
First off, note that IDisposable generally relates to external unmanaged resources1 - e.g. files, connections - and leaks of such; CLR objects and memory used by such will still be handled correctly by the GC based upon reachability.
IDisposable defines a contract and represents a breaking-change when added to or removed from a type. Any failure to honor this contract can result in "not well-defined behavior". The using
construct is a tool to avoid having to deal with the details of calling Dispose and edge-cases with exceptions, but it is not part of the contract and is not required. Yet, the contract remains the same and any violations of such removes all responsibility of said IDisposable to "work correctly".
Don't violate the contract.
1 An IDisposable type could also alter some state in Dispose that does not utilize unmanaged resources: this is still covered under "not well-defined behavior" if the contract is violated. One case where I have used an IDisposable type is to manage Runtime Callable Wrapper (RCW) objects even though they are technically "managed" by the runtime. See supercat's comment for more situations.
Upvotes: 2
Reputation: 81257
A correctly-written program which creates an instance of a type that implements IDisposable
, and which is not specifically known to be capable of adequately cleaning up after itself when abandoned, must ensure that Dispose
is called on that instance before abandoning it. Any program which fails to call Dispose
on a type which is not specifically known to be fine without it is broken.
Although it would be nice if automatic finalization could take care of everything, it's a pretty crummy cleanup mechanism. It provides no guarantees with regard to sequencing, threading context, timeliness, or certainty of completion (when using deterministic cleanup, one can make reasonably certain that a program won't appear to complete normally if cleanup fails; when using finalization, a program may appear to complete normally without even attempting to clean up an object).
Microsoft may once have intended that every IDisposable
class should be able to adequately clean up after itself if abandoned, but that is simply not practical. In many cases, for a class to attempt to clean up after itself if abandoned would add a massive amount of complexity, and would simply turn a broken program that would have obvious problems that are easy to track down, into a broken program that usually works except when the timing of the finalizer thread relative to some other thread causes things to fail in some unexpected and non-reproducible fashion.
There are some types which, despite implementing IDisposable
, are unconditionally safe to abandon, and there are some others which may be safely abandoned in certain circumstances. It is fine to abandon such types in situations where disposing them would be difficult (e.g. because references are held by multiple objects that are manipulated by various threads, and there's no nice way by which any particular object can know it when it holds the last surviving reference), provided that one documents one's reasons for believing that such action is safe and appropriate. Such behavior is not appropriate, however, in cases where one has accepted IDisposable
objects of unknown lineage.
Upvotes: 5
Reputation: 4340
Using
statement will call the object Dispose
method at the end of the block.
you can use the following example to get the same result:
obj a = new obj(); // Assuming obj : IDisposable
try
{
// Your code here
}
finally
{
if (a != null)
{
a.Dispose();
}
}
Upvotes: 0
Reputation: 35477
No it won't leak. Eventually garbage collection will get around to disposing the object.
IDisposable
allows the caller to free up the resources early.
Update
As @Servy and @Brian Rasmussen state. The class that implements IDisposable
should also implement a finalizer. This is the recommended practice. see http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.100).aspx
Upvotes: 2
Reputation: 33381
using
statement just syntactical sugar
using(var resource = expression) statement
which translates something likes to
{
var resource = expression;
try {
statement;
}
finally {
[if(resource!=null)]((IDisposable)resource).Dispose();
}
}
If dispose pattern implemented correctly the memory leak won't occurs. GC calls (non-deterministic) Finalizer
which calls Dispose
method.
Upvotes: 1
Reputation: 16934
It all depends on what your IDisposable
is.
The IDisposable
pattern is basically a way to deterministically release managed (and unmanaged) resources, rather than waiting until the finalizer for that object runs. If, for example, you open up database connections, file handles, etc., you will of course want these resources released or otherwise cleaned up "on demand", so they don't prevent you from re-acquiring access to them elsewhere. This is the main use case for the Dispose
pattern.
So, will it leak memory? Again, that depends - very likely, if you're using the IObervable<T>
subscriptions, since in one sense, they are un-released event handlers (I'm simplifying drastically here). Will you cause a memory leak if you don't close that SqlConnection
? Not by the strictest definition of "memory leak", as the connection will close eventually (say, when your app terminates, or the connection object is finally collected and finalized), but I think I can sum all this up by saying:
"ALWAYS dispose your IDisposables"
EDIT: @Servy is absolutely correct - while in my SqlConnection
example, I believe the finalizer automatically closes the connection, but this is NOT guaranteed behavior for IDisposables
in general - so always Dispose!
Upvotes: 1