So, the default dispose pattern implementation looks like this:
class SomeClass : IDisposable
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) {
// Free any other managed objects here.
}
// Free any unmanaged objects here.
disposed = true;
}
~SomeClass()
{
Dispose(false);
}
}
It's said that:
If the method call comes from a finalizer (that is, if disposing is
false), only the code that frees unmanaged resources executes. Because
the order in which the garbage collector destroys managed objects
during finalization is not defined, calling this Dispose overload with
a value of false prevents the finalizer from trying to release managed
resources that may have already been reclaimed.
The question is: why is it supposed that the objects that are referenced by the object of SomeClass may already have been freed and we shouldn't try to dispose them when the method is called from the finalizer? If those objects are still referenced by our SomeClass object they cannot be freed, isn't it true? It's said that:
Those with pending (unrun) finalizers are kept alive (for now) and are
put onto a special queue. [...] Prior to each object’s finalizer
running, it’s still very much alive — that queue acts as a root
object.
So, again, our SomeClass object is referenced by this queue (which is the same as to be referenced by a root). And other objects the SomeClass object has references to should be alive as well (as they are rooted through the SomeClass object). Then why and how they might have been freed by the time the SomeClass finalizer is called?
Konrad Kokosa has an impressive explanation on his book Pro .NET Memory Management.
(emphasis added)
During GC, at the end of Mark phase, GC checks the finalization queue to see if any of the finalizable objects are dead. If they are some, they cannot be yet delete because their finalizers will need to be executed. Hence, such object is moved to yet another queue called fReachable queue. Its name comes from the fact that it represents finalization reachable objects - the ones that are now reachable only because of finalization. If there are any such objects found, GC indicates to the dedicated finalizer thread there’s work to do.
Finalization thread is yet another thread created by the.NET runtime. It removes objects from the fReachable queue one by one and calls their finalizers. This happens after GC resumes managed threads because finalizer code may need to allocate objects. Since the only root to this object is removed from the fReachable queue, the next GC that condemns the generation this object is in will find it to be unreachable and reclaim it.
Moreover, fReachable queue is treated as a root considered during Mark phase because the finalizer thread may not be fast enough to process all objects from it between GCs. This exposes the finalizable objects more to a Mid-life crisis - they may stay in fReachable queue for a while consuming generation 2 just because of pending finalization.
I think the key here is:
fReachable queue is treated as a root considered during Mark phase because the finalizer thread may not be fast enough to process all objects from it between GCs.
Objects in .NET exist while any references exist to them. They cease to exist as soon as the last reference does so. Storage used by an object will never be reclaimed while the object exists, but there are a couple of things the GC does before it reclaims storage:
There is a special list, called the "finalizer queue", which holds references to all objects which have registered finalizers. After identifying every other reference that exists anywhere in the universe, the GC will examine all objects in the finalizer queue to see if any references have been found to them. If this process causes it to find an object which had not been discovered previously, it copies a reference to another list called the "freachable queue". Any time the freachable queue is non-empty and no finalizer is running, the system will pull a reference from that queue and call finalize upon it.
The GC will also inspect the targets of all weak references and invalidate any weak reference whose target hadn't been identified by any live strong reference.
Note that a finalize method does not "garbage-collect" an object. Instead, it prolongs the existence of the object until finalize is called upon it, for purpose of allowing it to satisfy any obligations it might have to outside entities. If at that time no reference to the object exists anywhere in the universe, the object will cease to exist.
Note that it's possible for two objects with finalizers to hold references to each other. In such situations, the order in which their finalizers run is unspecified.
I have a class (Model) an object of which serves as a blueprint for (short-lived) objects of another class (ModeledRelation). Model defines an event ModeledRelation always subscribes to in order to be notified when Model changes, so ModeledRelation objects can reflect these changes 1:1.
Now ModeledRelation objects are used somewhere else for some time and then finally go out of scope. But because the event still holds a reference to them they prevent garbage collection.
Of course I formally want the objects to be GC'ed already if the event is the only reference left. I know I can unsubscribe from the event in ModeledRelation.Dispose but that would require explicitely calling Dispose and this feels a little too crafty for a purely managed class. I also want to be safe in the case that the ModeledRelation object silently slips out of scope and not have a memory leak then.
Maybe I am thinking in a totally wrong direction and this has to be done differently.
You should look at the Weak Event Patterns :
https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/weak-event-patterns
Upon meditating about the problem throughout the day I have recognized what is the core issue about my approach: subscribing to the event during construction of ModeledRelation. This leads to the natural conclusion that unsubscription has to be done during object destruction... which never happens because event still points to the object and GC is blocked.
Instead the right solution to the problem is to subscribe to the event when the ModeledRelation is actually used (in my case added to another object's collection). Because then the natural moment to unsubscribe is when it ceases to be used (if it is removed from the collection of the other object). If it is reused afterwards it will resubscribe, whereas if it slips out of scope it will just be GC'ed because no events point to it anymore!
I can't find an answer to this.
Lets say I have created an object A that contains other objects B, C, etc.
Object A will first be created and added to an observable collection. Later object A is removed from the Observable collection. The ObservableCollection held the only reference to object A.
Is there any way Object A can detect it will be destroyed such that object A can manually call B.dispose and C.dispose and prevent memory leaks?
This is in .Net 4.0, but object B and C are .Net 3.5 or com objects and I'm not sure they will be disposed automatically when A is disposed. (I may be wrong).
Thanks in advance.
Yes. When an object is no longer reachable, it becomes eligible for garbage collection. If it is the sole root for objects it references, they also become eligible for collection. If it has a finalizer, this finalizer will be called by the GC. There are many aspects to understand with respect to deterministic and non-deterministic disposal of objects. Its references may be finalized before it is, or vice-versa. Start here:
http://msdn.microsoft.com/en-us/library/system.object.finalize(v=vs.100).aspx
You can use Dispose Pattern for this case. I am not sure if this can help you case. But if you are the owner of Object B & C then you can have dispose pattern implemented in B & C so that A can call b.dispose / c.dispose whenever its done.
I would implement Dispose on Object A and ensure it is called when removed from the collection. It's an observable collection so you should be able to get an object to subscribe to the collection and call dispose on objects removed from the collection which implement IDispose.
The Dispose Pattern calls dispose in the Finalizer simply as a fail safe, it's not intended to be the primary means of ensuring objects are disposed correctly, ideally you should be calling Dispose as soon as the object is no longer needed.
Most resources state that the garbage collector figures that out on its own based on references and that I shouldn't mess with it.
I am wondering if I can explicitly tell the garbage collector that it may dispose an object while still keeping a reference.
What I would like to do is to tell the garbage collector that I currently don't need an object anymore (but might again) and then at a later point when (if) I need the object again I would like to check if it has been disposed already. If it has I simply recreate it, if it hasn't I'd like to "unmark" it from garbage collection until I am done with it again.
Is this possible?
I plan to implement something similar to the Lazy<T> class. Pseudocode:
obj = new DisposeIfNecessary<LargeObject>(() => InitLargeObject());
obj.DoSomething(); // Initializes obj using InitLargeObject()
obj.DisposeIfNecessary(); // This is where the magic happens
... // obj might get disposed at some point
obj.DoAnotherThing(); // Might or might not call InitLargeObject() again
obj.Dispose(); // I will not need it again
The WeakReference class does exactly what you want, using the IsAlive property to check for state before using it.
You can get a "strong" reference to it again via the Target property, which will affect the reference count and stop it from being eligible for collection.
Also note that Dispose doesn't directly relate to garbage collection, so disposing an item (depending on the Dispose implementation) might make it unusable anyway - but again, that is nothing to do with GC. On a general practice note, as mentioned by #HansPassant, calling Dispose on an item (or generally anything claiming to dispose) and then attempting to use it again afterwards is a code smell (or just plain wrong as other developers will expect Dispose to be a last-call method marking the object as unusable from then on).
The WeakReference class will not be responsible for re-creating collected objects, but in conjunction with IsAlive you can handle that logic yourself.
Also, to the point in the comments, the GC doesn't do anything clever with WeakReference in terms of deciding when to collect it in terms of trying to leave WeakReference items until last; it will collect the underlying object as it would others during a run if it is eligible - no special handling and definitely no "cache" behaviour.
I have a class that should delete some file when disposed or finalized. Inside finalizers I can't use other objects because they could have been garbage-collected already.
Am I missing some point regarding finalizers and strings could be used?
UPD: Something like that:
public class TempFileStream : FileStream
{
private string _filename;
public TempFileStream(string filename)
:base(filename, FileMode.Open, FileAccess.Read, FileShare.Read)
{
_filename = filename;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (_filename == null) return;
try
{
File.Delete(_filename); // <-- oops! _filename could be gc-ed already
_filename = null;
}
catch (Exception e)
{
...
}
}
}
Yes, you can most certainly use strings from within a finalizer, and many other object types.
For the definitive source of all this, I would go pick up the book CLR via C#, 3rd edition, written by Jeffrey Richter. In chapter 21 this is all described in detail.
Anyway, here's what is really happening...
During garbage collection, any objects that have a finalizer that still wants to be called are placed on a special list, called the freachable list.
This list is considered a root, just as static variables and live local variables are. Therefore, any objects those objects refer to, and so on recursively is removed from the garbage collection cycle this time. They will survive the current garbage collection cycle as though they weren't eligible to collect to begin with.
Note that this includes strings, which was your question, but it also involves all other object types
Then, at some later point in time, the finalizer thread picks up the object from that list, and runs the finalizer on those objects, and then takes those objects off that list.
Then, the next time garbage collection runs, it finds the same objects once more, but this time the finalizer no longer wants to run, it has already been executed, and so the objects are collected as normal.
Let me illustrate with an example before I tell you what doesn't work.
Let's say you have objects A through Z, and each object references the next one, so you have object A referencing object B, B references C, C references D, and so on until Z.
Some of these objects implement finalizers, and they all implement IDisposable. Let's assume that A does not implement a finalizer but B does, and then some of the rest does as well, it's not important for this example which does beyond A and B.
Your program holds onto a reference to A, and only A.
In an ordinary, and correct, usage pattern you would dispose of A, which would dispose of B, which would dispose of C, etc. but you have a bug, so this doesn't happen. At some point, all of these objects are eligible for collection.
At this point GC will find all of these objects, but then notice that B has a finalizer, and it has not yet run. GC will therefore put B on the freachable list, and recursively take C, D, E, etc. up to Z, off of the GC list, because since B suddenly became in- eligible for collection, so does the rest. Note that some of these objects are also placed on the freachable list themselves, because they have finalizers on their own, but all the objects they refer to will survive GC.
A, however, is collected.
Let me make the above paragraph clear. At this point, A has been collected, but B, C, D, etc. up to Z are still alive as though nothing has happened. Though your code no longer has a reference to any of them, the freachable list has.
Then, the finalizer thread runs, and finalizes all of the objects in the freachable list, and takes the objects off of the list.
The next time GC is run, those objects are now collected.
So that certainly works, so what is the big bruaha about?
The problem is with the finalizer thread. This thread makes no assumptions about the order in which it should finalize those objects. It doesn't do this because in many cases it would be impossible for it to do so.
As I said above, in an ordinary world you would call dispose on A, which disposes B, which disposes C, etc. If one of these objects is a stream, the object referencing the stream might, in its call to Dispose, say "I'll just go ahead and flush my buffers before disposing the stream." This is perfectly legal and lots of existing code do this.
However, in the finalization thread, this order is no longer used, and thus if the stream was placed on the list before the objects that referenced it, the stream is finalized, and thus closed, before the object referencing it.
In other words, what you cannot do is summarized as follows:
You can not access any objects your object refer to, that has finalizers, as you have no guarantee that these objects will be in a usable state when your finalizer runs. The objects will still be there, in memory, and not collected, but they may be closed, terminated, finalized, etc. already.
So, back to your question:
Q. Can I use strings in finalizer method?
A. Yes, because strings do not implement a finalizer, and does not rely on other objects that has a finalizer, and will thus be alive and kicking at the time your finalizer runs.
The assumption that made you take the wrong path is the second sentence of the qustion:
Inside finalizers I can't use other objects because they could have been garbage-collected already.
The correct sentence would be:
Inside finalizer I can't use other objects that have finalizers, because they could have been finalized already.
For an example of something the finalizer would have no way of knowing the order in which to correctly finalize two objects, consider two objects that refer to each other and that both have finalizers. The finalizer thread would have to analyze the code to determine in which order they would normally be disposed, which might be a "dance" between the two objects. The finalizer thread does not do this, it just finalizes one before the other, and you have no guarantee which is first.
So, is there any time it is safe to access objects that also have a finalizer, from my own finalizer?
The only guaranteed safe scenario is when your program/class library/source code owns both objects so that you know that it is.
Before I explain this, this is not really good programming practices, so you probably shouldn't do it.
Example:
You have an object, Cache, that writes data to a file, this file is never kept open, and is thus only open when the object needs to write data to it.
You have another object, CacheManager, that uses the first one, and calls into the first object to give it data to write to the file.
CacheManager has a finalizer. The semantics here is that if the manager class is collected, but not disposed, it should delete the caches as it cannot guarantee their state.
However, the filename of the cache object is retrievable from a property of the cache object.
So the question is, do I need to make a copy of that filename into the manager object, to avoid problems during finalization?
Nope, you don't. When the manager is finalized, the cache object is still in memory, as is the filename string it refers to. What you cannot guarantee, however, is that any finalizer on the cache object hasn't already run.
However, in this case, if you know that the finalizer of the cache object either doesn't exist, or doesn't touch the file, your manager can read the filename property of the cache object, and delete the file.
However, since you now have a pretty strange dependency going on here, I would certainly advice against it.
Another point not yet mentioned is that although one might not expect that an object's finalizer would ever run while an object is in use, the finalization mechanism does not ensure that. Finalizers can be run in an arbitrary unknown threading context; as a consequence, they should either avoid using any types that aren't thread-safe, or should use locking or other means to ensure that they only use things in thread-safe fashion. Note finalizers should use Monitor.TryEnter rather than Monitor.Enter, and endeavor to act as gracefully as possible if a lock is unexpectedly held. Note that since finalizers aren't supposed to run while an object is still in use, the fact that a lock was unexpectedly held will often suggest that a finalizer was run early. Depending upon the design of the code which uses the lock, it may be possible to have the finalizer set a flag and try again to acquire the lock, and have any other code which uses the lock check after releasing it whether that flag is set and, if so, reregister the object for finalization.
Handling finalization cleanup correctly in all threading scenarios is difficult. Finalization might not seem complicated, but no convenient automated mechanisms exist by which objects can ensure that finalizers won't run while the objects in question are in use. Consequently, finalizers have a lot of subtle thread-safety issues. Code which ignores such issues will "usually" work, but may sometimes fail in difficult-to-diagnose ways.
You can call the dispose method inside your finalizer and have the file cleanup code in the Dispose method. Along with that you can also pass a boolean to your dispose method that indicates that you are invoking it from the finalizer.
For an excellent reference on the proper usage of Dispose and Fianlizers , read this Proper use of the IDisposable interface