C# Finalizer not freeing unmanaged memory - c#

I have a MappedMemory class that allocates a chunk of memory via Marshal.AllocHGlobal(). The class implements IDisposable, and I have it set up to auto-dispose the allocated memory when the class is finalized. However, it does not appear to be working as intended.
class MappedMemory : IDisposable
{
private bool disposed_ = false;
private IntPtr memoryPtr_;
public MappedMemory( int capacity )
{
memoryPtr_ = Marshal.AllocHGlobal( capacity );
}
~MappedMemory()
{
Dispose( false );
}
public void Dispose()
{
Dispose( true );
GC.SuppressFinalize( this );
}
protected virtual void Dispose( bool disposing )
{
if ( !disposed_ )
{
if ( disposing )
{
// Clear managed resources
}
Marshal.FreeHGlobal( memoryPtr_ );
}
disposed_ = true;
}
}
I have written two tests to ensure that the memory is being freed properly:
public MappedMemory_finalizer_frees_memory()
{
for( var i = 0; i < 1e8; i++ )
{
var memory = new MappedMemory( 128 );
}
}
public MappedMemory_dispose_frees_memory()
{
for( var i = 0; i < 1e8; i++ )
{
var memory = new MappedMemory( 128 );
memory.Dispose();
}
}
When the tests are run, the test that manually calls Dispose() works as it should, and memory stays at a constant utilization.
The test for the finalizer, however, does not appear to be freeing the allocated memory, and it leaks out of control until it runs out of memory. I have set a breakpoint and the call to Marshal.FreeHGlobal( memoryPtr_ ) is hit.
Manually adding GC.Collect() to the test fixes the problem, so ultimately it appears that the memory is deallocated, but not garbage collected?
I am super confused as to what is happening here. Can someone explain why the finalizer does not free the memory, and how I can ensure that it does in production?

From the MSDN documentation here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/destructors
The programmer has no control over when the finalizer is called
because this is determined by the garbage collector. The garbage
collector checks for objects that are no longer being used by the
application. If it considers an object eligible for finalization, it
calls the finalizer (if any) and reclaims the memory used to store the
object.
As you say that forcing garbage collection frees the memory I suspect that the issue you're seeing is that there isn't enough pressure on the memory systems to cause garbage collection to run automatically. Garbage collection is a relatively expensive process so it is not run unless there is a reason to do so.

Related

What is the resulting behavior when an IDisposable is passed into a parent IDisposable

Yesterday, after running Visual Studio code analysis on our codebase, the following code was highlighted as an issue:
using (var stringReader = new StringReader(someString))
{
using (var reader = XmlReader.Create(stringReader)) {
// Code
}
}
The warning that was returned was
Warning CA2202 Object 'stringReader' can be disposed more than once in
method '(method name)'. To avoid generating a
System.ObjectDisposedException you should not call Dispose more than
one time on an object.
After searching stack overflow, I've come to the general understanding that if I were to create a custom class containing IDisposable members, it should implement IDisposable itself, and call the dispose() method of the member.
My two questions are
In all cases where object X takes a reference to an IDisposable object Y as a parameter during creation, is it correct to assume that the object X will take ownership of Y and from that point onwards, calling X.dispose() will always result in calling Y.dispose()
This is an old piece of code and exceptions as described in the warning message have never been reported (to the best of my knowledge). If the above point is assumed, why does the double using block not result in calling stringReader.dispose() twice and therefore throwing an exception?
is it correct to assume that the object X will take ownership of Y and from that point onwards, calling X.dispose() will always result in calling Y.dispose()
No, it is never save to assume that. Let's check this specific case: XmlReader.Create(Stream).
After going to quite some code in the Reference Source, I have found that the Dispose method calls the Close method. That is quite obvious. Then notice this piece of code:
public override void Close() {
Close( closeInput );
}
So whether the backing stream will be closed and disposed depends on the value of the setting closeInput, which you can set through the XmlReaderSettings.CloseInput setting.
So the answer here is a definite no: you can't be sure it is disposed. You should always make sure yourself it is.
No, you cannot assume that another object will call Dispose() while disposing itself. The object having the disposable object as a reference might not even be using the disposable resource.
This warning is known to be somewhat weird. Look here to see some complaints about the warning. You should design your class so that it must be safe to call Dispose() more than once.
By the way, MSDN says:
A method implementation contains code paths that could cause multiple calls to IDisposable.Dispose or a Dispose equivalent, such as a Close() method on some types, on the same object.
So a path to the Close() method call can generate this warning too, which is why you see this warning in your case.
In all cases where object X takes a reference to an IDisposable object Y as a parameter during creation, is it correct to assume that the object X will take ownership of Y and from that point onwards, calling X.dispose() will always result in calling Y.dispose()
I think not and I will try to explain why.
There is a pattern called IDisposablePattern which looks something like that:
public class SimpleClass : IDisposable
{
// managed resources SqlConnection implements IDisposable as well.
private SqlConnection _connection;
private bool _disposed;
// implementing IDisposable
public void Dispose()
{
// Here in original Dispose method we call protected method with parameter true,
// saying that this object is being disposed.
this.Dispose(true);
// Then we "tell" garbage collector to suppress finalizer for this object because we are releasing
// its memory and doesnt need to be finalized. Calling finalizer(destructor) of a given type is expensive
// and tweaks like this help us improve performance of the application.
GC.SuppressFinalize(this);
}
// Following the best practices we should create another method in the class
// with parameter saying whether or not the object is being disposed.
// Its really important that this method DOES NOT throw exceptions thus allowing to be called multiple times
protected virtual void Dispose(bool disposing)
{
// another thing we may add is flag that tells us if object is disposed already
// and use it here
if (_disposed) { return; }
if (_connection != null)
{
_connection.Dispose();
_connection = null;
}
_disposed = true;
// call base Dispose(flag) method if we are using hierarchy.
}
}
Note that this can be extended to new level when your class uses unmanaged resources like this one:
public class SimpleClass2: IDisposable
{
// managed resources
private SqlConnection _connection;
private bool _disposed;
// unmanaged resources
private IntPtr _unmanagedResources;
// simple method for the demo
public string GetDate()
{
// One good practice that .NET Framework implies is that when object is being disposed
// trying to work with its resources should throw ObjectDisposedException so..
if(_disposed) { throw new ObjectDisposedException(this.GetType().Name);}
if (_connection == null)
{
_connection = new SqlConnection("Server=.\\SQLEXPRESS;Database=master;Integrated Security=SSPI;App=IDisposablePattern");
_connection.Open();
}
// allocation of unmanaged resources for the sake of demo.
if (_unmanagedResources == IntPtr.Zero)
{
_unmanagedResources = Marshal.AllocHGlobal(100 * 1024 * 1024);
}
using (var command = _connection.CreateCommand())
{
command.CommandText = "SELECT getdate()";
return command.ExecuteScalar().ToString();
}
}
public void Dispose()
{
// Here in original Dispose method we call protected method with parameter true,
// saying that this object is being disposed.
this.Dispose(true);
// Then we "tell" garbage collector to suppress finalizer for this object because we are releasing
// its memory and doesnt need to be finalized. Calling finalizer(destructor) of a given type is expensive
// and tweaks like this help us improve performance of the application.
// This is only when your class doesnt have unmanaged resources!!!
// Since this is just made to be a demo I will leave it there, but this contradicts with our defined finalizer.
GC.SuppressFinalize(this);
}
// Following the best practices we should create another method in the class
// with parameter saying wether or not the object is being disposed.
// Its really important that this method DOES NOT throw exceptions thus allowing to be called multiple times
protected virtual void Dispose(bool disposing)
{
// another thing we may add is flag that tells us if object is disposed already
// and use it here
if (_disposed) { return; }
// Thus Dispose method CAN NOT release UNMANAGED resources such as IntPtr structure,
// flag is also helping us know whether we are disposing managed or unmanaged resources
if (disposing)
{
if (_connection != null)
{
_connection.Dispose();
_connection = null;
}
_disposed = true;
}
// Why do we need to do that?
// If consumer of this class forgets to call its Dispose method ( simply by not using the object in "using" statement
// Nevertheless garbage collector will fire eventually and it will invoke Dispose method whats the problem with that is if we didn't
// have the following code unmanaged resources wouldnt be disposed , because as we know GC cant release unmanaged code.
// So thats why we need destructor(finalizer).
if (_unmanagedResources != IntPtr.Zero)
{
Marshal.FreeHGlobal(_unmanagedResources);
_unmanagedResources = IntPtr.Zero;;
}
// call base Dispose(flag) method if we are using hierarchy.
}
~DatabaseStateImpr()
{
// At this point GC called our finalizer method , meaning
// that we don't know what state our managed resources are (collected or not) because
// our consumer may not used our object properly(not in using statement) so thats why
// we skip unmanaged resources as they may have been finalized themselves and we cant guarantee that we can
// access them - Remember? No exceptions in Dispose methods.
Dispose(false);
}
}

when object goes out of scope in c #?

Method where scopes defined explicitly.
static void Main(string[] args)
{
Class1 c1 = new Class1(1);
{
Class1 c2 = new Class1(2);
{
Class1 c3 = new Class1(3);
}
//this is not collecting object c3 which is out of scope here
GC.Collect();
}
//this is not collecting object c2 which is out of scope here
GC.Collect();
Console.ReadKey();
}
Class1 definition:
class Class1
{
int x;
public Class1(int a)
{
x = a;
}
~Class1()
{
Console.WriteLine(x + "object destroy");
}
}
I write this code. But GC.Collect() method don't collect the object which goes out of scope.
GC.Collect() isn't really meant to be used for deterministic reclamation of resources. (That is what your finalizers in your real code is doing, right?)
If you have an unmanaged resource to deal with, strong consider using one of the classes in Microsoft.Win32.SafeHandles.
If you want deterministic release of resources, you should implement IDisposable, and call Dispose() when you are done using the object. The idiomatic way of doing this is:
using (var someResource = new Class1(1))
{
// work with the `Class1` object
}
which is functionally equivalent to
{
var someResource = new Class1(1);
try
{
// work with the `Class1` object
}
finally
{
someResource.Dispose();
}
}
What you think about scoping is correct. Objects are going out of scope exactly as you expect. However, apparently the way you are testing it is not so correct.
Couple of points to consider here.
You should implement the finalizer only if you have any unmanaged resources.
If your class has a finalizer and if you don’t implement IDisposable Correctly in a way that it the suppress the finalization, instances of that class can reside in memory for two garbage collection cycles. Because, the first GC.Collect add that instance to the finalization queue if it requires finalization. May be the second garbage collection cycle actually clears the memory.
Finalizer is the last point where .net objects can release unmanaged resources.
Finalizers are to be executed only if you don’t dispose your instances correctly. Ideally, finalizers should never be executed. Because proper dispose implementation should suppress the finalization.
According to your sample code, if you call GC.Collect and WaitForPendingFinalizers your test may pass (not sure how to find if memory is cleared).
Better test for you.
Garbage collector doesn't take inner scopes into account when clearing memory. If you move your code into a separate method it executes the finalizer.
Test 1
static void Main(string[] args)
{
GCTest();
Console.ReadKey();
}
private static void GCTest()
{
Class1 c1 = new Class1(1);
{
Class1 c2 = new Class1(2);
{
Class1 c3 = new Class1(3);
}
//this is not collecting object c3 which is out of scope here
GC.Collect();
GC.WaitForPendingFinalizers();
}
//this is not collecting object c2 which is out of scope here
GC.Collect();
GC.WaitForPendingFinalizers();
}
Test 2
Use using statement if you want to specify scoping for garbage collection purposes.
private static void Main(string[] args)
{
using (Class1 c1 = new Class1(1))
{
using (Class1 c2 = new Class1(2))
{
Class1 c3 = new Class1(3);
}
}
Console.ReadKey();
}
class Class1 : IDisposable
{
int x;
public Class1(int a)
{
x = a;
}
public void Dispose()
{
Console.WriteLine(x + "object disposing");
}
}
Output
2object disposing
1object disposing
Theses scopes do not make it into IL. The runtime has no idea they were there. At the IL level there are just locals and stack contents. Although the .NET JIT is poor in general it does a decent job of optimizing locals and temporary values into an efficient form.
There are no guarantees when objects will be collected. GC.Collect can't force that. There are some safe patterns to have it 99.999% guaranteed but never fully.
You never need this facility. In fact the need to have a finalizer is almost zero. Use the SafeHandle infrastructure.
If you really want to see the effect, move all of this code into a helper method and call that from Main. Back in main the Collect will succeed.

Will I cause a memory leak by assigning new value[] to a filled array

I have an array that works more or less like a hastable:
based on an index, a value will be placed in the array, so some indices of the array will have values inside, others might not or will not.
I have two pieces of code:
public void register( int index, string value )
{
_array[index] = value;
}
public void unregisterAll( )
{
/*
is this going to cause a memory leak when some of the values
are filled int the above function?
*/
_array = new string[12];
}
C# uses a garbage collector. If an object is no longer referenced it is (after some time) free'd automatically.
This is what happens (from the perspective of the garbage collector (GC)) when you execute unregisterAll()
object_array`1: referenced by _array
// execute unregisterAll();
create object_array`2 and let _array reference it
// Some time later when the GC runs
object_array`1: not referenced
object_array`2: referenced by _array
// Some time later, when the GC decided to collect
collect object__array`1
Note that this doesn't mean you cannot have a memory leak in C#. Some objects use unmanaged resources which need to be disposed manually (they implement the interface IDisposable which you can dispose of automatically by scoping it in a using block:
using(IDisposable disposable = new ...)
{
// use it
} // when leaving this scope disposable.Dispose() is automatically called
Or which you can dispose of manually by calling Dispose() on them.

Memory leak when ThreadLocal<T> is used in cyclic graph

I just came across this weird 'behavior' of the Garbage Collector concerning System.Threading.ThreadLocal<T> that I can't explain. In normal circumstances, ThreadLocal<T> instances will be garbage collected when they go out of scope, even if they aren't disposed properly, except in the situation where they are part of a cyclic object graph.
The following example demonstrates the problem:
public class Program
{
public class B { public A A; }
public class A { public ThreadLocal<B> LocalB; }
private static List<WeakReference> references = new List<WeakReference>();
static void Main(string[] args) {
for (var i = 0; i < 1000; i++)
CreateGraph();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
// Expecting to print 0, but it prints 1000
Console.WriteLine(references.Count(c => c.IsAlive));
}
static void CreateGraph() {
var a = new A { LocalB = new ThreadLocal<B>() };
a.LocalB.Value = new B { A = a };
references.Add(new WeakReference(a));
// If either one of the following lines is uncommented, the cyclic
// graph is broken, and the programs output will become 0.
// a.LocalB = null;
// a.LocalB.Value = null;
// a.LocalB.Value.A = null;
// a.LocalB.Dispose();
}
}
Although not calling Dispose is not good practice, but it's the CLR's design to clean up resources (by calling the finalizer) eventually, even if Dispose is not called.
Why does ThreadLocal behave differently in this regard and can cause memory leaks when not disposed properly in case of a cyclic graph? Is this by design? And if so, where is this documented? Or is this a bug in the CLR's GC?
(Tested under .NET 4.5).
Microsoft's David Kean confirmed that this actually is a bug.
The reason is that you're not calling Dispose. The garbage collector will only clean up objects that have finalizers as a last resort.

C# Destructor not working as expected

Please see the code below. I expect it to print either 10 because I have explicitly invoked the garbage collector. But I always get either a 0 or 20 as output. Why is that?
void Main()
{
Panda[] forest_panda = new Panda[10];
for(int i=0; i<forest_panda.GetLength(0);i++)
{
forest_panda[i]=new Panda("P1");
}
for(int i=0; i<forest_panda.GetLength(0);i++)
{
forest_panda[i]=new Panda("P1");
}
System.GC.Collect();
Console.WriteLine("Total Pandas created is {0}",Panda.population);
}
class Panda
{
public static int population=0;
public string name;
public Panda(string name)
{
this.name = name;
population = population + 1;
}
~Panda()
{
population = population - 1;
}
}
Please note that the class for Main is automatically created by LINQPad (the editor that comes with the "C# 4.0 in a Nutshell" book). I am new to C#.
You have not run an explict garbage collection. From the docs of GC.Collect():
Use this method to attempt to reclaim
all memory that is inaccessible.
However, the Collect method does not
guarantee that all inaccessible memory
is reclaimed.
All objects, regardless of how long
they have been in memory, are
considered for collection; however,
objects that are referenced in managed
code are not collected. Use this
method to force the system to attempt
to reclaim the maximum amount of
available memory.
The garabage collector is highly optimized and "decides" all by himself when he actually does the garbage collection and then call the finalizers. Additionally it is all done asynchronously. That is also why Finalizers are called non-deterministic cleanup. You never now when cleanup happens.
You have two options now. You can either call GC.WaitForPendingFinalizers() wich will halt the current thread until the all finalizable objects have been finalized. Or call this new overload: System.GC.Collect(int generation, System.GCCollectionMode mode) with GCCollectionMode.Forced It was introduced in .NET 3.5.
Just keep in mind that usually it is not necessary and more importantly: a bad idea to call the garbage collector manually. Also implementing the finalizer is only needed in rare occasions. Calling the garbage collector will slow down the runtime. Implementing finalizers will slow down the runtime additionally. The garabge collector puts all objects that implement the finalizer into the finalization queue when they are ready to be garabge collected. Processing this queue is expensive.
To make things worse, when the finalizer is run, it is not guaranteed that the members you are trying to access there are still alive. It is very well possible they have already been grabage collected. That's why you should use the finalizer only when you have unmanaged resources that need to be cleaned up.
All this is definately not needed in your example. What you acutally want is IDisposable for deterministic cleanup.
There are a couple of things to notice here:
First of all the GC behaves differently between release and debug builds. Generally, in release mode objects can be reclaimed sooner than in debug mode.
As Tim points out calling GC.Collect doesn't call finalizers. If you want to wait for finalizers to run call GC.WaitForPendingFinalizers as well.
Finalizers are run by a dedicated thread, so you're actually modifying state from two different threads without any synchronization. While this may not be a problem in this particular case, doing so is not a good idea. But before you go and add synchronization to your finalizer, please keep in mind that a deadlocked finalizer means that no more finalizers will run and thus the memory for those objects will not be reclaimed.
Try adding System.GC.WaitForPendingFinalizers after you garbage collect.
http://www.developer.com/net/csharp/article.php/3343191/C-Tip-Forcing-Garbage-Collection-in-NET.htm
You create twenty objects, so the value would then be 20. Explicitly calling System.GC.Collect() does not actually guarantee calling the destructor. Therefore if it was called all 20 objects may have been destructed or none may have been.
This explains what is actually happening.
It isn't good practice to create a destructor or call GC.Collect explicitly.
If An object needs to do cleanup, it should implement IDisposable
In .NET, object lifetimes are non-deterministic and do not behave as you'd expect from C++ constructor/destructors. In fact, .NET objects do not technically have destructors. The finalizer differs in that it is expected to clean up unmanaged resources used by the object during it's lifetime.
To have a deterministic way of freeing resources used by your object, you implement the IDisposable interface. IDisposable isn't perfect though as it still requires the calling code to correctly dispose of the object when it's done, and it's hard to handle accidental multiple calls to Dispose. However syntax in C# makes this generally very easy.
class Panda : IDisposable
{
public static int population = 0;
public string _name;
public Panda( string name )
{
if( name == null )
throw new ArgumentNullException( name );
_name = name;
population++;
}
protected virtual void Dispose( bool disposing )
{
if( disposing && name != null )
{
population--;
name = null;
}
}
public void Dispose()
{
Dispose( true );
GC.SuppressFinalize( this );
}
~Panda(){ Dispose( false ); }
}
Then to use the class:
using( var panda = new Panda( "Cute & Cuddly" ) )
{
// Do something with the panda
} // panda.Dispose() called automatically
Using destructors (a.k.a. finalizers) is not really a good way of doing things in C#. There is no guarantee that the finalizer will ever run, even if you explicitly invoke the garbage collector. You shouldn't try to force garbage collection either, because it will probably have a negative perfomance impact on your application overall.
Instead, if you need to explicitly free resources owned by an object, you should implement the IDisposable interface, and place your cleanup logic inside the Dispose() method. Conversely, when you use an object that implements IDisposable, you should always take care to call its Dispose() method when you are finished with it. C# provides the "using" statement for this purpose.
Many classes that do I/O (such as Streams) implement IDisposable. Here is an example of using a FileStream to read a text file. Note the "using" statement to ensure the FileStream is disposed when we are finished with it:
using (FileStream fs = File.OpenRead("C:\\temp\\myfile.txt"))
{
// Read a text file 1024 bytes at a time and write it to the console
byte[] b = new byte[1024];
while (fs.Read(b, 0, b.Length) > 0)
{
Console.WriteLine(Encoding.UTF8.GetString(b));
}
} // Dispose() is called automatically here
The above code is equivalent to this:
FileStream fs = File.OpenRead("C:\\temp\\myfile.txt"))
try
{
// Read a text file 1024 bytes at a time and write it to the console
byte[] b = new byte[1024];
while (fs.Read(b, 0, b.Length) > 0)
{
Console.WriteLine(Encoding.UTF8.GetString(b));
}
}
finally
{
fs.Dispose();
}
The Disposing Pattern would be the best to use.
Here's the full implementation of your work.
Remember, that you have to call Dispose by your own like done in the code below.
public static void Main()
{
Panda[] forest_panda = new Panda[10];
for (int i = 0; i < forest_panda.GetLength(0); i++)
forest_panda[i] = new Panda("P1");
// Dispose the pandas by your own
foreach (var panda in forest_panda)
panda.Dispose();
for (int i = 0; i < forest_panda.GetLength(0); i++)
forest_panda[i] = new Panda("P1");
// Dispose the pandas by your own
foreach (var panda in forest_panda)
panda.Dispose();
Console.WriteLine("Total Pandas created is {0}", Panda.population);
}
class Panda : IDisposable
{
public static int population = 0;
public string name;
public Panda(string name)
{
this.name = name;
population = population + 1;
}
~Panda()
{
Dispose(false);
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <filterpriority>2</filterpriority>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing)
{
population = population - 1;
}
}
}
It invoked for me in release build . However behaved differently in debug.

Categories