Finalizer not being called after garbage collection - c#

I have a test program that implements ManagedClass with both Dispose method and a Finalizer.
I'm forcing garbage collection via GC.Collect(), but Finalizer is only called if an object is created in a separate method. Why is that?
namespace FinalizerTest
{
internal class Program
{
static void Run()
{
ManagedClass mc = new ManagedClass();
mc.StartWriting();
}
static void Main(string[] args)
{
Console.WriteLine("Let's test Finalizers!");
// Test #1: Create object through another method
Console.WriteLine("Test #1");
Run();
GC.Collect();
GC.WaitForPendingFinalizers();
// Test #2: Create object directly in Main
Console.WriteLine("Test #2");
ManagedClass mc1 = new ManagedClass();
mc1.StartWriting();
mc1 = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.ReadLine();
}
}
public class ManagedClass : IDisposable
{
private StreamWriter _writer;
public void StartWriting()
{
_writer = new StreamWriter("output.txt");
}
public void Dispose()
{
Console.WriteLine("Disposing");
_writer?.Dispose();
GC.SuppressFinalize(this);
}
~ManagedClass()
{
Console.WriteLine("Finalizing");
_writer?.Dispose();
}
}
}
As I understand it in both scenarios a reference to the object is lost.
First test - reference is lost by exiting the scope of the method
Second test - reference is lost by setting reference variable to null
However, Finalizer is consistently only ever called after the first test.
According to Microsoft documentation:
The garbage collector then calls the Finalize method automatically under the following conditions:
After the garbage collector has discovered that an object is inaccessible, unless the object has been exempted from finalization by a call to the GC.SuppressFinalize method.
I'm not calling GCSuppressFinalize and according to Visual Studio I'm working on .NET 7.0
I tried:
Reassigning a new reference instead of null
Implementing Finalizer without the Dispose method
Running in Release configuration / building the project and running the application directly through exe file
None of those things called Test #2 Finalizer

Sometimes GC.Collect doesn't work perfectly.
To improve the garbage collection, I call the following procedure :
internal static void CollectGarbage(int SizeToAllocateInMo)
{ // set SizeToAllocateInMo to -1 to force garbage collection without testing available memory.
long [,] TheArray ;
bool DoCollect=SizeToAllocateInMo<0 ;
if (!DoCollect) try { TheArray = new long[SizeToAllocateInMo,125000] ; } catch { DoCollect=true ; }
TheArray=null ;
if (DoCollect)
{
GC.Collect() ;
GC.WaitForPendingFinalizers() ;
SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle,-1,-1) ;
GC.Collect() ;
}
}
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize); // used for garbage collection

Related

C# destructor not called even after code scope + GC? [duplicate]

This question already has answers here:
Understanding garbage collection in .NET
(2 answers)
Closed 2 years ago.
I've got a simple test code in Nunit+.net core 2.0 under VS2019:
public class Tests
{
public static int i = 0;
class First
{
~First()
{
i += 1;
Console.WriteLine("First's destructor is called.");
}
}
class Second : First
{
~Second() { i += 10; Console.WriteLine("Second's destructor is called."); }
}
class Third : Second
{
~Third() { i += 100; Console.WriteLine("Third's destructor is called."); }
}
[Test]
public static void Test()
{
{
Third t = new Third();
}
Thread.Sleep(1000);
System.GC.Collect();
Assert.AreEqual(111, i);
}
}
It always fails, while I found finally i=0, and the destructors are called right after Test(). But you can see the "t" is in a code block, and is invalid after the code block, and I also called
System.GC.Collect();
before my "Assert".
Why destructor is not called even after GC? How to fix my code to make the test pass?
Thanks a lot.
Use using statement and the IDisposable interface instead destructor;
public class Tests
{
public static int i = 0;
class First : IDisposable
{
public virtual void Dispose()
{
i += 1; Console.WriteLine("First's Dispose is called.");
}
}
class Second : First
{
public override void Dispose()
{
i += 10; Console.WriteLine("Second's Dispose is called.");
base.Dispose();
}
}
class Third : Second
{
public override void Dispose()
{
i += 100; Console.WriteLine("Third's Dispose is called.");
base.Dispose();
}
}
public static void Test()
{
using (Third t = new Third()) {
Console.WriteLine("Now everything will be ok, after leaving this block");
Console.WriteLine("t object will be dispose");
}
Thread.Sleep(1000);
System.GC.Collect();
Assert.AreEqual(111, i);
}
}
You can call System.GC.Collect() but it is not matter. The destructor will not be call immediately as you expect. (In above code you don't need System.GC.Collect())
It is strange to me why Microsoft does not make this clearer, instead of the old definition "Forces an immediate garbage collection of all generations." which leads developers to think they should expect an immediate result and GC.Collect() should wait for garbage collection to be complete before it returns?!
GC.Collect Method(System) - Microsoft Docs
Even more strange to me is that the code they give as an example for using of GC.Collect() don't work as they claim, for the same reason. You can try yourself by commenting GC.Collect(); line. I don't know, maybe they just don't update their documents as often. Maybe the situation was different before with GC.Collect()?! GC.CollectRequest() would be a more appropriate name for this function, if you ask me.
P.s. I'm new to C# so please, excuse me if I say things that do not fully understand or something I'm wrong in the code I write.
Call GC.WaitForPendingFinalizers() after GC.Collect()
The finalizers (not destructors) run as background tasks asynchronously, so after you call GC.Collect() and reach the assertion statement the finalizers are not guaranteed to have finished.

Can .NET detect "irrelevant" code at runtime and garbage-collect objects in it?

Suppose I have a C# method like this
public void foo(){
Object very_large_object;
if (very_large_object.some_runtime_condition ()) {
do_something ();
return;
}
do_something_else (very_large_object);
}
In my case, do_something is an expensive method and may take some time to finish. When it's running, can .NET GC detects that do_something_else won't be called and thus very_larget_object is no longer relevant and garbage-collects it?
Yes it can. It's a common misconception that object lifetime is somehow related to the enclosing scope (for example that very_large_object can only be collected when foo scope ends). You can verify your particular case with simple application:
class Program {
static void Main() {
var o = new TestObject();
var test = Console.ReadKey();
if (test.Key == ConsoleKey.Enter) {
DoSomething();
Console.ReadKey();
return;
}
DoSomethingElse(o);
}
static void DoSomething() {
Console.WriteLine("doing something");
Thread.Sleep(500);
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("GC ran");
}
static void DoSomethingElse(TestObject o) {
Console.WriteLine(o);
}
}
public class TestObject {
public TestObject() {
}
~TestObject() {
Console.WriteLine("finalizer running");
}
}
If you compile that in Release mode with optimizations enabled, it will output the following (after you press Enter in console):
doing something
finalizer running
GC ran
So it's clear that o was considered garbage and was put into finalizer queue while we were still inside DoSomething method. Optimizer could not just throw away branch with DoSomethingElse because it depends on your console input whether it will run or not. If you remove return then of course it won't be collected.

How to dispose managed and unmanaged objects in C#?

all. I've never worked with destructors nor dispose, so this is new to me.
I have a task of doing a class that has destructor and dispose methods, and that has a UInt64 Id property that is auto-incremental, and a static Dictionary<UInt64,MyClass> that must reference by Id all live instances of MyClass.
After searching how to use them properly, this is what I ended up doing:
public class MyClass : IDisposable
{
private static Object Lock = new Object();
private static Dictionary<UInt64, MyClass> LiveInstances = new Dictionary<UInt64, MyClass>();
public UInt64 Id { get; private set; }
public MyClass()
{
lock (Lock)
{
var newId = IncrementalId();
if (newId == 0)
{
throw new ArgumentException("Reached MAX VAL");
}
Id = newId;
LiveInstances.Add(Id, this);
}
}
~MyClass()
{
CleanUpNativeResources();
}
public void Dispose()
{
lock (Lock)
{
CleanUpManagedResources();
CleanUpNativeResources();
GC.SuppressFinalize(this);
}
}
protected virtual void CleanUpManagedResources()
{
LiveInstances.Remove(Id);
}
protected virtual void CleanUpNativeResources()
{
}
private static UInt64 IncrementalId()
{
for (ulong i = 0; i <= Convert.ToUInt64(LiveInstances.Count) ; i++)
{
if (i != UInt64.MaxValue && !LiveInstances.ContainsKey(i + 1))
{
return i+1;
}
}
return 0;
}
}
Now, my question is How do I dispose objects? Whether I try to find examples of disposing objects, I find something like this:
// Code to dispose the managed resources of the class
Console.WriteLine("Object disposed");
Thanks in advance.
Managed resources will be disposed automatically by the garbage collector at some point of time. Unmanaged resources are things like Filehandles, obtained by making a Windows API call that returns a Windows Handle which must be freed manually. You dont have anything which requires manual disposal.
If you don't free those handles, they will remain allocated for the duration of the program, but all .Net classes that have an unmanaged resource provide a Finalizer (see below) to make sure that they will normally be freed at some point.
(But if you were writing your own file handling class and forgot to free the file handle anywhere at all, the file would remain open until your program exited.)
Normally such unmanaged resources will be freed in two places:
The Dispose() method. This should be the normal way that you dispose unmanaged resources.
The Finalizer. This is a last-resort mechanism. If a class has a finalizer it will be called by the Garbage Collector when it cleans up a dead object. Any class which has an unmanaged resource should have a finalizer to clean up if the programmer forgets to call Dispose().
The basic Dispose pattern used goes something like this:
class MyObject : IDisposable
{
//indicates if dispose has already been called
//private bool _disposed = false;
//Finalize method for the object, will call Dispose for us
//to clean up the resources if the user has not called it
~MyObject()
{
//Indicate that the GC called Dispose, not the user
Dispose(false);
}
//This is the public method, it will HOPEFULLY but
//not always be called by users of the class
public void Dispose()
{
//indicate this was NOT called by the Garbage collector
Dispose(true);
//Now we have disposed of all our resources, the GC does not
//need to do anything, stop the finalizer being called
GC.SupressFinalize(this);
}
private void Dispose(bool disposing)
{
//Check to see if we have already disposed the object
//this is necessary because we should be able to call
//Dispose multiple times without throwing an error
if (!disposed)
{
if (disposing)
{
//clean up managed resources
components.Dispose();
}
//clear up any unmanaged resources - this is safe to
//put outside the disposing check because if the user
//called dispose we want to also clean up unmanaged
//resources, if the GC called Dispose then we only
//want to clean up managed resources
}
}
}

Calling method after destructor runs

I've readed about this, but I forgot, where I saw an example. So it looks like this
public class Program
{
private static void Main()
{
new SomeClass(10).Foo();
}
}
public class SomeClass
{
public int I;
public SomeClass(int input)
{
I = input;
Console.WriteLine("I = {0}", I);
}
~SomeClass()
{
Console.WriteLine("deleted");
}
public void Foo()
{
Thread.Sleep(2000);
Console.WriteLine("Foo");
}
}
so output should be:
I = 10
deleted
Foo
why? due to optimizer. It sees that method doesn't use any field so it can destroy an object before the method is called. So why it doesn't do it?
I'l post an example if i found it.
so i found the source. Pro .NET Performance: Sasha Goldshtein , Dima Zurbalev , Ido Flatow
Another problem has to do with the asynchronous nature of finalization
which occurs in a dedicated thread. A finalizer might attempt to
acquire a lock that is held by the application code, and the
application might be waiting for finalization to complete by calling
GC.WaitForPendingFinalizers(). The only way to resolve this issue is
to acquire the lock with a timeout and fail gracefully if it can’t be
acquired. Yet another scenario is caused by the garbage collector’s
eagerness to reclaim memory as soon as possible. Consider the
following code which represents a naïve implementation of a File class
with a finalizer that closes the file handle:
class File3
{
Handle handle;
public File3(string filename)
{
handle = new Handle(filename);
}
public byte[] Read(int bytes)
{
return Util.InternalRead(handle, bytes);
}
~File3()
{
handle.Close();
}
}
class Program
{
static void Main()
{
File3 file = new File3("File.txt");
byte[] data = file.Read(100);
Console.WriteLine(Encoding.ASCII.GetString(data));
}
}
This innocent piece of code can break in a very nasty manner. The Read
method can take a long time to complete, and it only uses the handle
contained within the object, and not the object itself. The rules for
determining when a local variable is considered an active root dictate
that the local variable held by the client is no longer relevant after
the call to Read has been dispatched. Therefore, the object is
considered eligible for garbage collection and its finalizer might
execute before the Read method returns! If this happens, we might be
closing the handle while it is being used, or just before it is used.
but i can't reproduce this behaviour
public void Foo()
{
Thread.Sleep(1000);
Console.WriteLine("Foo");
}
Methods that don't use any instance member of a class should be declared static. Which has several advantages, it is for one very helpful to a reader of the code. It unambiguously states that a method doesn't mutate the object state.
And for another has the great advantage that you'll now understand why there's no discrepancy in seeing the method running after the object got finalized. The GC just doesn't have any reason to keep this alive, there are no references left to the object when Foo() starts executing. So no trouble at all getting it collected and finalized.
You'll find more background info on how the jitter reports object references to the garbage collector in this answer.
Anyway, i found the way to reproduce it, i just should read more attentive :) :
public class Program
{
private static void Main()
{
new Thread(() =>
{
Thread.Sleep(100);
GC.Collect();
}).Start();
new SomeClass(10).Foo();
}
}
public class SomeClass
{
public int I;
public SomeClass(int input)
{
I = input;
Console.WriteLine("I = {0}", I);
}
~SomeClass()
{
Console.WriteLine("deleted");
}
public void Foo()
{
Thread.Sleep(1000);
Console.WriteLine("Foo");
}
}
so in this case destructor will be called before Foo method.
The problem is because you're using threading in Foo. You tell the code to wait for 1 second, but you don't tell it to wait for the second to be up before executing everything else. Therefore the original thread executes the destructor before Foo finishes.
A better way of writing Foo would be something like this:
public void Foo()
{
var mre = new ManualResetEvent(false);
mre.WaitOne(1000);
Console.WriteLine("Foo");
}
Using the ManualResetEvent will force the code to completely pause until, in this case, the timeout is hit. After which the code will continue.

What's the use of the SyncRoot pattern?

I'm reading a c# book that describes the SyncRoot pattern. It shows
void doThis()
{
lock(this){ ... }
}
void doThat()
{
lock(this){ ... }
}
and compares to the SyncRoot pattern:
object syncRoot = new object();
void doThis()
{
lock(syncRoot ){ ... }
}
void doThat()
{
lock(syncRoot){ ... }
}
However, I don't really understand the difference here; it seems that in both cases both methods can only be accessed by one thread at a time.
The book describes ... because the object of the instance can also be used for synchronized access from the outside and you can't control this form the class itself, you can use the SyncRoot pattern Eh? 'object of the instance'?
Can anyone tell me the difference between the two approaches above?
If you have an internal data structure that you want to prevent simultaneous access to by multiple threads, you should always make sure the object you're locking on is not public.
The reasoning behind this is that a public object can be locked by anyone, and thus you can create deadlocks because you're not in total control of the locking pattern.
This means that locking on this is not an option, since anyone can lock on that object. Likewise, you should not lock on something you expose to the outside world.
Which means that the best solution is to use an internal object, and thus the tip is to just use Object.
Locking data structures is something you really need to have full control over, otherwise you risk setting up a scenario for deadlocking, which can be very problematic to handle.
The actual purpose of this pattern is implementing correct synchronization with wrappers hierarchy.
For example, if class WrapperA wraps an instance of ClassThanNeedsToBeSynced, and class WrapperB wraps the same instance of ClassThanNeedsToBeSynced, you can't lock on WrapperA or WrapperB, since if you lock on WrapperA, lock on WrappedB won't wait.
For this reason you must lock on wrapperAInst.SyncRoot and wrapperBInst.SyncRoot, which delegate lock to ClassThanNeedsToBeSynced's one.
Example:
public interface ISynchronized
{
object SyncRoot { get; }
}
public class SynchronizationCriticalClass : ISynchronized
{
public object SyncRoot
{
// you can return this, because this class wraps nothing.
get { return this; }
}
}
public class WrapperA : ISynchronized
{
ISynchronized subClass;
public WrapperA(ISynchronized subClass)
{
this.subClass = subClass;
}
public object SyncRoot
{
// you should return SyncRoot of underlying class.
get { return subClass.SyncRoot; }
}
}
public class WrapperB : ISynchronized
{
ISynchronized subClass;
public WrapperB(ISynchronized subClass)
{
this.subClass = subClass;
}
public object SyncRoot
{
// you should return SyncRoot of underlying class.
get { return subClass.SyncRoot; }
}
}
// Run
class MainClass
{
delegate void DoSomethingAsyncDelegate(ISynchronized obj);
public static void Main(string[] args)
{
SynchronizationCriticalClass rootClass = new SynchronizationCriticalClass();
WrapperA wrapperA = new WrapperA(rootClass);
WrapperB wrapperB = new WrapperB(rootClass);
// Do some async work with them to test synchronization.
//Works good.
DoSomethingAsyncDelegate work = new DoSomethingAsyncDelegate(DoSomethingAsyncCorrectly);
work.BeginInvoke(wrapperA, null, null);
work.BeginInvoke(wrapperB, null, null);
// Works wrong.
work = new DoSomethingAsyncDelegate(DoSomethingAsyncIncorrectly);
work.BeginInvoke(wrapperA, null, null);
work.BeginInvoke(wrapperB, null, null);
}
static void DoSomethingAsyncCorrectly(ISynchronized obj)
{
lock (obj.SyncRoot)
{
// Do something with obj
}
}
// This works wrong! obj is locked but not the underlaying object!
static void DoSomethingAsyncIncorrectly(ISynchronized obj)
{
lock (obj)
{
// Do something with obj
}
}
}
Here is an example :
class ILockMySelf
{
public void doThat()
{
lock (this)
{
// Don't actually need anything here.
// In this example this will never be reached.
}
}
}
class WeveGotAProblem
{
ILockMySelf anObjectIShouldntUseToLock = new ILockMySelf();
public void doThis()
{
lock (anObjectIShouldntUseToLock)
{
// doThat will wait for the lock to be released to finish the thread
var thread = new Thread(x => anObjectIShouldntUseToLock.doThat());
thread.Start();
// doThis will wait for the thread to finish to release the lock
thread.Join();
}
}
}
You see that the second class can use an instance of the first one in a lock statement. This leads to a deadlock in the example.
The correct SyncRoot implementation is:
object syncRoot = new object();
void doThis()
{
lock(syncRoot ){ ... }
}
void doThat()
{
lock(syncRoot ){ ... }
}
as syncRoot is a private field, you don't have to worry about external use of this object.
Here's one other interesting thing related to this topic:
Questionable value of SyncRoot on Collections (by Brad Adams):
You’ll notice a SyncRoot property on many of the Collections in System.Collections. In retrospeced (sic), I think this property was a mistake. Krzysztof Cwalina, a Program Manger on my team, just sent me some thoughts on why that is – I agree with him:
We found the SyncRoot-based synchronization APIs to be insufficiently flexible for most scenarios. The APIs allow for thread safe access to a single member of a collection. The problem is that there are numerous scenarios where you need to lock on multiple operations (for example remove one item and add another). In other words, it’s usually the code that uses a collection that wants to choose (and can actually implement) the right synchronization policy, not the collection itself. We found that SyncRoot is actually used very rarely and in cases where it is used, it actually does not add much value. In cases where it’s not used, it is just an annoyance to implementers of ICollection.
Rest assured we will not make the same mistake as we build the generic versions of these collections.
See this Jeff Richter's article. More specifically, this example which demonstrates that locking on "this" can cause a deadlock:
using System;
using System.Threading;
class App {
static void Main() {
// Construct an instance of the App object
App a = new App();
// This malicious code enters a lock on
// the object but never exits the lock
Monitor.Enter(a);
// For demonstration purposes, let's release the
// root to this object and force a garbage collection
a = null;
GC.Collect();
// For demonstration purposes, wait until all Finalize
// methods have completed their execution - deadlock!
GC.WaitForPendingFinalizers();
// We never get to the line of code below!
Console.WriteLine("Leaving Main");
}
// This is the App type's Finalize method
~App() {
// For demonstration purposes, have the CLR's
// Finalizer thread attempt to lock the object.
// NOTE: Since the Main thread owns the lock,
// the Finalizer thread is deadlocked!
lock (this) {
// Pretend to do something in here...
}
}
}
Another concrete example:
class Program
{
public class Test
{
public string DoThis()
{
lock (this)
{
return "got it!";
}
}
}
public delegate string Something();
static void Main(string[] args)
{
var test = new Test();
Something call = test.DoThis;
//Holding lock from _outside_ the class
IAsyncResult async;
lock (test)
{
//Calling method on another thread.
async = call.BeginInvoke(null, null);
}
async.AsyncWaitHandle.WaitOne();
string result = call.EndInvoke(async);
lock (test)
{
async = call.BeginInvoke(null, null);
async.AsyncWaitHandle.WaitOne();
}
result = call.EndInvoke(async);
}
}
In this example, the first call will succeed, but if you trace in the debugger the call to DoSomething will block until the lock is release. The second call will deadlock, since the Main thread is holding the monitor lock on test.
The issue is that Main can lock the object instance, which means that it can keep the instance from doing anything that the object thinks should be synchronized. The point being that the object itself knows what requires locking, and outside interference is just asking for trouble. That's why the pattern of having a private member variable that you can use exclusively for synchronization without having to worry about outside interference.
The same goes for the equivalent static pattern:
class Program
{
public static class Test
{
public static string DoThis()
{
lock (typeof(Test))
{
return "got it!";
}
}
}
public delegate string Something();
static void Main(string[] args)
{
Something call =Test.DoThis;
//Holding lock from _outside_ the class
IAsyncResult async;
lock (typeof(Test))
{
//Calling method on another thread.
async = call.BeginInvoke(null, null);
}
async.AsyncWaitHandle.WaitOne();
string result = call.EndInvoke(async);
lock (typeof(Test))
{
async = call.BeginInvoke(null, null);
async.AsyncWaitHandle.WaitOne();
}
result = call.EndInvoke(async);
}
}
Use a private static object to synchronize on, not the Type.

Categories

Resources