public void func1()
{
object obj= null;
try
{
obj=new object();
}
finally
{
obj = null;
}
}
is there any advantage of assigning null to a reference in finally block in regards of memory management of large objects?
Let's deal with the explicit and implicit questions here.
Q: First and foremost, is there a point in assigning null to a local variable when you're done with it?
A: No, none at all. When compiled with optimizations and not running under a debugger, the JITter knows the segment of the code where a variable is in use and will automatically stop considering it a root when you've passed that segment. In other words, if you assign something to a variable, and then at some point never again read from it, it may be collected even if you don't explicitly set it to null.
So your example can safely be written as:
public void func1()
{
object obj = new object();
// implied more code here
}
If no code in the "implied more code here" ever accesses the obj variable, it is no longer considered a root.
Note that this changes if running in a non-optimized assembly, or if you hook up a debugger to the process. In that case the scope of variables is artificially extended until the end of their scope to make it easier to debug.
Q: Secondly, what about fields in the surrounding class?
A: Here it can definitely make a difference.
If the object surrounding your method is kept alive for an extended period of time, and the need for the contents of a field has gone, then yes, setting the field to null will make the old object it referenced eligible for collection.
So this code might have merit:
public class SomeClass
{
private object obj;
public void func1()
{
try
{
obj=new object();
// implied more code here
}
finally
{
obj = null;
}
}
}
But then, why are you doing it like this? You should instead strive to write cleaner code that doesn't rely on surrounding state. In the above code you should instead refactor the "implied more code here" to be passed in the object to use, and remove the global field.
Obviously, if you can't do that, then yes, setting the field to null as soon as its object reference is no longer needed is a good idea.
Fun experiment, if you run the below code in LINQPad with optimizations on, what do you expect the output to be?
void Main()
{
var s = new Scary();
s.Test();
}
public class Scary
{
public Scary()
{
Console.WriteLine(".ctor");
}
~Scary()
{
Console.WriteLine("finalizer");
}
public void Test()
{
Console.WriteLine("starting test");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine("ending test");
}
}
Answer (mouseover to show when you think you've got it):
.ctor
starting test
finalizer
ending test
Explanation:
Since the implicit this parameter to an instance method is never used inside the method, the object surrounding the method is collected, even if the method is currently running.
Related
I have a question about the following code:
DisposableObject holdon = null;
using (DisposableObject o = new DisposableObject())
{
Console.WriteLine("Inside using block");
holdon = o;
}
holdon.Method();
When I ran this code, I expected to get an exception on the line holdon.Method(), but to my surprise, It happily called Method() without any problem. I was able to confirm that DisposableObject.Dispose() is being called on o upon hitting the end of the using block. This raises a question that I didn't have a lot of luck finding the answer to on MSDN. After the using block, holdon is definitely still pointing to a valid object in memory despite the fact that Dispose() was called. So does holdon still point to the same object previously pointed to by o, or does it point to a copy of o?
Disposing object is not related to removing object from memory. It only means calling Dispose() method on that object. All further actions depend on IDisposable implementation of the object you have disposed. In some cases object is set to 'disposed' state and all further actions raise an exception (ObjectDisposedException). But you are free to do anything (or not do) when you implement IDisposable.
E.g. this is a totally valid IDisposable implementation (fiddle):
public class CrazyDisposable : IDisposable
{
public int Counter { get; private set; }
public void Dispose() => Counter++;
}
Further reading: using statement (C# Reference).
And particularly part which explains why it's better to limit the scope of the disposable object to the using block:
You can instantiate the resource object and then pass the variable to
the using statement, but this is not a best practice. In this case,
the object remains in scope after control leaves the using block even
though it will probably no longer have access to its unmanaged
resources. In other words, it will no longer be fully initialized. If
you try to use the object outside the using block, you risk causing an
exception to be thrown. For this reason, it is generally better to
instantiate the object in the using statement and limit its scope to
the using block.
as you can see - it's allowed, but you risk when you access the disposed object.
the using statement is just shorthand for
DisposableObject holdon = null;
{ //This "{" is here to limit the scope of "o"
DisposableObject o = new DisposableObject()
try
{
Console.WriteLine("Inside using block");
holdon = o;
}
finally
{
if(o != null)
o.Dispose();
}
}
holdon.Method();
So if calling
o.Dispose();
o.Method();
in normal code does not cause a exception then calling holdon.Method() after o.Dispose() will not cause a exception either.
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.
I noticed the following object disposal code pattern in a C# project and I was wondering if it's acceptable (although it works).
public object GetData()
{
object obj;
try
{
obj = new Object();
// code to populate SortedList
return obj;
}
catch
{
return null;
}
finally
{
if (obj != null)
{
obj.Dispose();
obj = null;
}
}
}
For this example, I'm using a general 'object' instead of the actual IDisposable class in the project.
I know that the 'finally' block will be executed every time, even when the value is returned, but would it affect the return value (or would it be a new object instance) in any way since the object is being set to null (for what seems like object disposal and GC purposes).
Update 1:
I tried the following snippet and the return object is non-null, although the local object is set to null, so it works, which is a bit strange considering some of the comments below:
public StringBuilder TestDate()
{
StringBuilder sb;
try
{
sb = new StringBuilder();
sb.Append(DateTime.UtcNow.ToString());
return sb;
}
catch
{
return null;
}
finally
{
sb = null;
}
}
Btw, I'm using C# 4.0.
P.S. I'm just reviewing this project code. I'm not the original author.
Update 2:
Found the answer to this mystery [1]. The finally statement is executed, but the return value isn't affected (if set/reset in the finally block).
[1] What really happens in a try { return x; } finally { x = null; } statement?
This code will compile fine (assuming that you are not actually using an Object but something that implements IDisposable), but it probably won't do what you want it to do. In C#, you don't get a new object without a new; this code will return a reference to an object that has already been disposed, and depending on the object and what Dispose() actually does, trying to use a disposed object may or may not crash your program.
I assume the idea is to create an object, do some stuff with it, then return the object if successful or null (and dispose the object) on failure. If so, what you should do is:
try {
obj = new MyClass();
// ... do some stuff with obj
return obj;
}
catch {
if(obj != null) obj.Dispose();
return null;
}
Simply using the using statement achieves the same result as that, and is the standard practice
public int A()
{
using(IDisposable obj = new MyClass())
{
//...
return something;
}
}
I would, however, advise against returning your IDisposable object.
When you dispose of an object, it is supposed to be considered "unusable". And so, why return it?
If the object's lifetime needs to be longer than the method A's lifetime, consider having the calling method B instantiate the object, and pass it as a parameter to method A.
In this case, method Bwould be the one using the using statement, inside which it would call A.
If you are returning an IDisposable object, then it is the responsibility of your caller to dispose of it:
public IDisposable MakeDisposableObject()
{
return new SqlConnection(""); // or whatever
}
caller:
using (var obj = MakeDisposableObject())
{
}
It makes less than no sense for your method to dispose of an object and then return it. The disposed object will be of no value to the caller. In general, referencing a disposable object which has been disposed should produce an ObjectDisposedException.
A few observations.
That code wouldn't compile because object doesn't have a .Dispose() method.
Why wouldn't you use IDisposable?
Why would you dispose of an object that is being returned, since returning you would return an object for the purpose of some other code to use it. The concept of "disposing" of something is to give it a chance to clean up after itself and its used, un-managed resources. If you are returning an object that is supposed to be used elsewhere, but has unmanaged resources that you want to clean up before the object gets used anywhere else, then you shuld really have 2 separate objects. One to load some data that would be disposable, and another object that would contain the usable loaded content that you want to pass around. An example of this would be something like stream readers in the .NET framework. You would normally new a stream reader, read it into a byte[] or some other data object, .Dispose() the stream reader, then return the byte[]. The "loader" that has some resources to dispose of in a timely fashion is separate from the object containing the "loaded" data that can be used without needing to be disposed.
I have a number of static List's in my application, which are used to store data from my database and are used when looking up information:
public static IList<string> Names;
I also have some methods to refresh this data from the database:
public static void GetNames()
{
SQLEngine sql = new SQLEngine(ConnectionString);
lock (Names)
{
Names = sql.GetDataTable("SELECT * FROM Names").ToList<string>();
}
}
I initially didnt have the lock() in place, however i noticed very occasionally, the requesting thread couldnt find the information in the list. Now, I am assuming that if the requesting thread tries to access the Names list, it cant until it has been fully updated.
Is this the correct methodology and usage of the lock() statement?
As a sidenote, i noticed on MSDN that one shouldnt use lock() on public variables. Could someone please elaborate in my particular scenario?
lock is only useful if all places intended to be synchronized also apply the lock. So every time you access Names you would be required to lock. At the moment, that only stops 2 threads swapping Names at the same time, which frankly isn't a problem here anyway, as reference swaps are atomic anyway.
Another problem; presumably Names starts off null? You can't lock a null. Equally, you shouldn't lock on something that may change reference. If you want to synchronize, a common approach is something like:
// do not use for your scenario - see below
private static readonly object lockObj = new object();
then lock(lockObj) instead of your data.
With regards to not locking things that are visible externally; yes. That is because some other code could randomly choose to lock on it, which could cause unexpected blocking, and quite possibly deadlocks.
The other big risk is that some of your code obtains the names, and then does a sort/add/remove/clear/etc - anything that mutates the data. Personally, I would be using a read-only list here. In fact, with a read-only list, all you have is a reference swap; since that is atomic, you don't need any locking:
public static IList<string> Names { get; private set; }
public static void UpdateNames() {
List<string> tmp = SomeSqlQuery();
Names = tmp.AsReadOnly();
}
And finally: public fields are very very rarely a good idea. Hence the property above. This will be inlined by the JIT, so it is not a penalty.
No, it's not correct since anyone can use the Names property directly.
public class SomeClass
{
private List<string> _names;
private object _namesLock = new object();
public IEnumerable<string> Names
{
get
{
if (_names == null)
{
lock (_namesLock )
{
if (_names == null)
_names = GetNames();
}
}
return _names;
}
}
public void UpdateNames()
{
lock (_namesLock)
GetNames();
}
private void GetNames()
{
SQLEngine sql = new SQLEngine(ConnectionString);
_names = sql.GetDataTable("SELECT * FROM Names").ToList<string>();
}
}
Try to avoid static methods. At least use a singleton.
The check, lock, check is faster than a lock, check since the write will only occur once.
Assigning a property on usage is called lazy loading.
The _namesLock is required since you can't lock on null.
From the oode you have shown, the first time GetNames() is called the Names property is null. I don't known what a lock on a null object would do. I would add a variable to lock on.
static object namesLock = new object();
Then in GetNames()
lock (namesLock)
{
if (Names == null)
Names = ...;
}
We do the if test inside of the lock() to stop race conditions. I'm assuming that the caller of GetNames() also does the same test.
I'd like to use .NET's Lazy<T> class to implement thread safe caching. Suppose we had the following setup:
class Foo
{
Lazy<string> cachedAttribute;
Foo()
{
invalidateCache();
}
string initCache()
{
string returnVal = "";
//CALCULATE RETURNVAL HERE
return returnVal;
}
public String CachedAttr
{
get
{
return cachedAttribute.Value;
}
}
void invalidateCache()
{
cachedAttribute = new Lazy<string>(initCache, true);
}
}
My questions are:
Would this work at all?
How would the locking have to work?
I feel like I'm missing a lock somewhere near the invalidateCache, but for the life of me I can't figure out what it is.
I'm sure there's a problem with this somewhere, I just haven't figured out where.
[EDIT]
Ok, well it looks like I was right, there were things I hadn't thought about. If a thread sees an outdated cache it'd be a very bad thing, so it looks like "Lazy" is not safe enough. The Property is accessed a lot though, so I was engaging in pre-mature optimization in hopes that I could learn something and have a pattern to use in the future for thread-safe caching. I'll keep working on it.
P.S.: I decided to make the object thread-un-safe and have access to the object be carefully controlled instead.
Well, it's not thread-safe in that one thread could still see the old value after another thread sees the new value after invalidation - because the first thread could have not seen the change to cachedAttribute. In theory, that situation could perpetuate forever, although it's pretty unlikely :)
Using Lazy<T> as a cache of unchanging values seems like a better idea to me - more in line with how it was intended - but if you can cope with the possibility of using an old "invalidated" value for an arbitrarily long period in another thread, I think this would be okay.
cachedAttribute is a shared resource that needs to be protected from concurrent modification.
Protect it with a lock:
private readonly object gate = new object();
public string CachedAttr
{
get
{
Lazy<string> lazy;
lock (gate) // 1. Lock
{
lazy = this.cachedAttribute; // 2. Get current Lazy<string>
} // 3. Unlock
return lazy.Value // 4. Get value of Lazy<string>
// outside lock
}
}
void InvalidateCache()
{
lock (gate) // 1. Lock
{ // 2. Assign new Lazy<string>
cachedAttribute = new Lazy<string>(initCache, true);
} // 3. Unlock
}
or use Interlocked.Exchange:
void InvalidateCache()
{
Interlocked.Exchange(ref cachedAttribute, new Lazy<string>(initCache, true));
}
volatile might work as well in this scenario, but it makes my head hurt.