27
votes

I was reading the MSDN article about how to implement IDisposable and I am uncertain about the difference between managed and native resources cited in the article.

I have a class that must dispose 2 of its fields when it is disposed. Should I treat them as Managed (dispose only when disposing = true) or Native resources?

3

3 Answers

23
votes

To add a little to Brian's answer, and your comment/question:

The difference between a Managed/Unmanaged resource is that the Garbage Collector is aware of managed resources and isn't aware of unmanaged resources. I know that answer isn't very concrete but the difference is huge.

To help draw the line in the sand here is the short (and probably riddled with little errors) version of how GC runs and cleans up memory:

The garbage collector is aware of all managed objects but when garbage collection runs it doesn't initially know if any given object is still in use or is elegible to be released. It determines whether or not it can cleanup an object by initially marking all objects as garbage, then traversing from the application root to all referenced objects. Each object that has a relationship back to the root (a reference, either direct or indirect) gets marked as reachable and is no longer considered garbage. After the GC runs through every reachable object it cleans up the rest since they are no longer in use.

In almost all cases working with .NET framework objects you can be assured that objects are managed (.NET provides managed wrappers of nearly all unmanaged resources to ensure they are properly cleaned up); other third party components which hook into the Win32 API (or your components which do this) are the objects which may be cause for concern.

There are some .NET objects which can be considered to be somewhat unmanaged. Components of the Graphics library are one example.

Most ".NET Memory leaks" aren't really memory leaks in the true sense. Typically they occur when you think you have removed an object from use but in fact the object still has some reference to the application. A common example is adding eventhandlers (obj.SomeEvent += OnSomeEvent -or- AddHandler obj.SomeEvent, AddressOf OnSomeEvent) and not removing them.

These 'lingering references' are technically not memory leaks since your application is still technically using them; however if there are enough of them your application can suffer severe performance impacts and may show signs of resource issues (OutOfMemoryExceptions, unable to attain window handles, etc).

I'm an intermediate .NET developer and unfortunately know about these problems first-hand. I recommend playing with ANTS Profiler to help become familiar with lingering references (there is a free trial version) or if you want to get a little bit more nitty-gritty research using WinDbg and SOS.DLL to look at the managed heap. If you decide to look into the latter I recommend reading Tess Ferrandez' blog; she has a lot of great tutorials and advice on using Windbg effectively

19
votes

A managed resource is another managed type, which implements IDisposable. You need to call Dispose() on any other IDisposable type you use. Native resources are anything outside the managed world such as native Windows handles etc.


EDIT: Answer to question in comment (too long for comment)

No that is just a managed type. A correctly constructed type, which doesn’t implement IDisposable will be handled by the garbage collector and you don’t have to do anything else. If your type uses a native resource directly (e.g. by calling Win32 libraries), you must implement IDisposable on your type and dispose of the resource(s) in the Dispose method. If your type uses a native resource encapsulated by another type which implements IDisposable, you must call Dispose() on instances of this type in the Dispose method of your type.

1
votes

The short answer would be anything that you go behind the CLR's back (to the OS) to obtain can be termed as 'native'.

  • unmanaged memory allocation. If you 'new' up a chunk of memory in a managed class CantStayManaged, then CantStayManaged is responsible for freeing this memory (resource).
  • handles to files, pipes, events, synchronization constructs, etc. - as a thumb rule if you call WinAPIs to obtain pointers/handles to a resource, then those are 'native resources'

So now CantStayManaged has 2 things it needs to cleanup before it bids adieu.

  1. Managed: Member fields and any resources the CLR allocated. This usually equates to calling Dispose on your 'Disposable' member objects.
  2. Unmanaged: all the sneaky low-level stuff we pull behind its back.

There are 2 ways the object cleanup can be triggered now.

  1. Dispose(true) case: You called Dispose explicitly on your type. Good programmer.
  2. Dispose(false) case: You forgot to call Dispose, in which case the finalizer should kick in and still ensure proper cleanup.

In both cases, the unmanaged resources should be freed up else 'LEAKS!', 'CRASHES!' et.all surface. But you should only attempt to cleanup managed resources only in Dispose() former case. In the latter/finalizer case - the CLR might have already finalized and collected some of your members, so you shouldn't access them (CLR doesn't guarantee an order in which an object graph is finalized.) Hence you avoid issues by guarding your managed cleanup with an if (AmIBeingCalledFromDispose) guard check

HTH