Instance variable lifetime in classes vs structs - c#

I know that an instance variable of a class comes to life when a new instance of that class is instantiated and when there are no references to that instance, the instance's destructor has executed. But what about instance variables lifetime in structs?
Thanks.

and when there are no references to that instance, the instance's destructor has executed
Only if that class has a destructor (otherwise, its memory is simply reclaimed), if GC.SuppressFinalize hasn't been called on that object, and when the Garbage Collector decides to collect the generation to which that object belongs.
Also note that destroying an object isn't the same as reclaiming its memory.
When the GC calls an object's destructor, the object will be promoted to the next generation, and its memory will only be reclaimed the next time the GC decides to collect that generation, if there are still no strong references to it.
And this is why it's possible (but don't do it!) to resurrect an object, by creating a strong reference to itself (e.g., assigning itself to a static field) within the destructor.
But what about instance variables lifetime in structs?
If they're declared within a method and not leaked anywhere (such as using it in a closure, or being assigned to a field member), chances are they'll be put on the stack and deleted deterministically when the method ends, and the GC will never know about it.
If they're assigned to a field, they'll live as long as the enclosing class lives.
Also, structs can't have destructors.

First of all, it is not true, that if there are no references to the instance, it's destructor is being called. What really happens is that at the time of Garbage Collector's choice the object is marked as garbage and then later, again at the time of Garbage Collector's choice the object is destroyed.
In case of structures, you have to remember, that structure behaves similarly as any other value-type object (such as int, float and so on). So, for example, if you keep structure in a local variable and exit the method, structure is deleted from the stack, thus clearing all references to its all fields - and if they are reference-typed (and no other references exists), they will be collected by the GC in the same manner I described earlier. If they are value-typed, they are deleted immediately.
You can read more about this matter in article and on msdn

You should probably read up on Garbage Collection, as the assumptions you make are outright wrong. When nothing references an object, GC may collect it, but you won't know precisely when. Also, C# has no destructors, it has finalizers, which aren't deterministic as opposed to destructors. The syntax is the same as the C++ destructor, but under the hood they're different.
The difference between reference types (classes) and value types (structs), is that reference types are garbage collected if there is no valid reference to them anymore, where value types are collected when they go out of scope. Types like int, IntPtr, etc are all structs and follow the same rules.

As per MSDN:
"An instance variable of a struct has exactly the same lifetime as the struct variable to which it belongs i.e, when a variable of a struct type comes into existence or ceases to exist, so too do the instance variables of the struct."
Source: http://msdn.microsoft.com/en-us/library/aa691165(v=vs.71).aspx
(Although it is destroyed by the Garbage Collector actually).

Related

Delete the memory of a Double data type variable

I'm trying to use Garbage collector, GC.collect(), to delete the memory of my variables after a certain period of time that my program runs. It worked well and did what I needed for my integer variables, however when I attempted this for my Double variables or Long it ran an error, stating that GC.collect is integer based.
My question is, is there an alternative service method that I can use to clear the memory of my variables that are of type double or Long?
Thanks
You can pass an int variable to GC.Collect(n), but it means "collect nth generation," not "remove n."
You misunderstand entirely how garbage collectors work. GC is an automated process, and you don't need to remove references from memory explicitly. To eliminate memory leaks, you should not leave unnecessary references and dispose of all the disposable objects when they are no longer needed.
I might also mention that the garbage collector only cares about objects, i.e. classes. Value types, i.e. int, double, structs, etc are either part of a object, and thus tracked and collected as part of that object. Or part of the stack, and thus released automatically when the method they are used in returns.

When an array is subject to Garbage Collection?

A few years ago I read the book the CLR via C# and the other day I got asked whether an array and still got a bit puzzled, the question was to figure out when the array in the method below is available to garbage collection:
public static double ThingRatio()
{
var input = new [] { 1, 1, 2 ,3, 5 ,8 };
var count = input.Length;
// Let's suppose that the line below is the last use of the array input
var thingCount = CountThings(input);
input = null;
return (double)thingCount / count;
}
According to the answer given here: When is an object subject to garbage collection? which states:
They will both become eligible for collection as soon as they are not
needed anymore. This means that under some circumstances, objects can
be collected even before the end of the scope in which they were
defined. On the other hand, the actual collection might also happen
much later.
I would tend to say that starting after line 6 (i.e. input = null;) the array becomes subject to GC but I am not that sure... (I mean the array is supposedly surely no longer needed after the assignment, but also struggling that it's after the CountThings call but at the same time the array is "needed" for the null assignment).
Remember objects and variables are not the same thing. A variable has a scope to particular method or type, but the object it refers to or used to refer to has no such concept; it's just a blob of memory. If the GC runs after input = null; but before the end of the method, the array is just one more orphaned object. It's not reachable, and therefore eligible for collection.
And "reachable" (rather then "needed" ) is the key word here. The array object is no longer needed after this line: var thingCount = CountThings(input);. However, it's still reachable, and so could not be collected at that point...
We also need to remember it isn't collected right away. It's only eligible to be collected. As a practical matter, I've found the .Net runtime doesn't tend to invoke the GC in the middle of a user method unless it really has to. Generally speaking, it is not needed or helpful to set a variable to null early, and in some rare cases can even be harmful.
Finally, I'll add that the code we read and write is not the same code actually used by the machine. Remember, there is also a compile step to translate all this to IL, and later a JIT process to create the final machine code that really runs. Even concept of one line following next is already an abstraction away from what actually happens. One line may expand to be several lines of actual IL, or in some cases even be re-written to involve all new compiler-generated types as with closures or iterator blocks. So everything here is really only referring to the simple case.
GC Myth: setting an object's reference to null will force the GC to collect it right away.
GC Truth: setting an object's reference to null will sometimes allow the GC to collect it sooner.
Taking part of the blogpost I'm referencing below and applying it to your question, the answer is as follows:
The JIT is usually smart enough to realize that input = null can be optimized away. That leaves CountThings(input) as the last reference to the object. So after that call, the input is no longer used and is removed as a GC Root. That leaves the Object in memory orphaned (no references pointing to it), making it eligible for collection. When the GC actually goes about collecting it, is another matter.
More information to be found at To Null or Not to Null
No object can be garbage-collected while it is recognized as existing. An object will exist in .NET for as along as any reference to it exists or it has a registered finalizer, and will cease to exist once neither condition applies. References in objects will exist as long as the objects themselves exist, and references in automatic variables will exist as long as there is any means via which they will be observed. If the garbage collector detects that the only references to an object with no registered finalizer are held in weak references, those references will be destroyed, causing the object to cease to exist. If the garbage collector detects that the only references to an object with a registered finalizer are held in weak references, any weak references whose "track resurrection" property is false, a reference to the object will be placed in a strongly-rooted list of objects needing "immediate" finalization, and the finalizer will be unregistered (thus allowing it to cease to exist if and when the finalizer reaches a point in execution where no reference to the object could ever be observed).
Note that some sources confuse the triggering of an object's finalizer with garbage-collection, but an object whose finalizer is triggered is guaranteed to continue to exist for at least as long as that finalizer takes to execute, and may continue to exist indefinitely if any references to it exist when the finalizer finishes execution.
In your example, there are three scenarios that could apply, depending upon what CountThings does with the passed-in reference:
If CountThings does not store a copy of the reference anywhere, or any copies of references that it does store get overwritten before input gets overwritten, then it will cease to exist as soon as input gets overwritten or ceases to exist [automatic-duration variables may cease to exist any time a compiler determines that their value will no longer be observed].
If CountThings stores a copy of the reference somewhere that continues to exist after it returns, and the last extant reference is held by something other than a weak reference, then the object will cease to exist as soon as the last reference is destroyed.
If the last existing reference the array ends up being held in a weak reference, the array will continue to exist until the first GC cycle where that is the case, whereupon the weak reference will be cleared, causing the array to cease to exist. Note that the lack of non-weak references to the array will only be relevant when a GC cycle occurs. It is possible (and not particularly uncommon) for a program to store a copy of a reference into a WeakReference, ConditionalWeakTable, or other object holding some form of weak reference, destroy all other copies, and then read out the weak reference to produce a non-weak copy of the reference before the next GC cycle. If that occurs, the system will neither know nor care that there was a time when non non-weak copies of the reference existed. If the GC cycle occurs before the reference gets read out, however, then code which later examines the weak reference will find it blank.
A key observation is that while finalizers and weak references complicate things slightly, the only way in which the GC destroys objects is by invalidating weak forms of references. As far as the GC is concerned, the only kinds of storage that exist when the system isn't actually performing a GC cycle are those used by objects that exist, those used for .NET's internal purposes, and regions of storage that are available to satisfy future allocations. If an object is created, the storage it occupied will cease to be a region of storage available for future allocations. If the object later ceases to exist, the storage that had contained the object will also cease to exist in any form the GC knows about until the next GC cycle. The next GC cycle won't destroy the object (which had already ceased to exist), but will instead add the storage which had contained it back to its list of areas that are available to add future allocations (causing that storage to exist again).

Are static class members pinned?

I have a C# class, having a static ImageList object. This image list will be shared with various ListView headers (via SendMessage... HDM_SETIMAGELIST) on several forms in my application.
Though I understand that static objects are not eligible for garbage collection, it is not clear to me if they are also ineligible for relocation (compaction) by the garbage collector. Do I also need to pin this object since it is shared with unmanaged code, say, using GCHandle.Alloc?
Environment is VS 2008, Compact Framework 3.5.
The instance itself is not static. The reference is. If you null the reference the instance becomes eligible for GC. Internally, all static instances are references through a pinned handle to an array of statics. I.e. the instance is implicitly pinned by the runtime.
If you look at the GCroot of an instance declared as a static member, you'll see something like this:
HandleTable:
008113ec (pinned handle)
-> 032434c8 System.Object[]
-> 022427b0 System.Collections.Generic.List`1[[System.String, mscorlib]]
If you null the static reference the corresponding entry in the pinned array is nulled as well.
Now, these are obviously implementation details so they could potentially change.
Yes. You need to pin the object.
While it's true that the reference is static, that is, you may access this location anywhere from your member it's reference is still a GC handle. That is, it's eligible for garbage collection (and/or compaction) but it will of course never happen.
I don't think it's necessarily wrong to think that the static modifier implies that it will eventually have a static location in memory but there bigger issue is that there's no API that allows you to get at the memory address without pinning the object. Whether it's being moved by the GC or not.
Moreover, each static member is unqiue per AppDomain (not process). The same static member could exist in different memory locations in the same process and it can be garbage collected when the AppDomain unloads. This is quite the edge case I'll admit but there's no real advantage of not pinning objects even if it could be done without pinning.
Do I also need to pin this object since it is shared with unmanaged
code, say, using GCHandle.Alloc?
Yes. If the pointer is not pinned, GC is free to move that memory, so you may have dangling C++ pointers, pointing to some non valid, or worse, non their memory at all.
Also, "shared" word should be clarified. If you allocate and pass to unmanaged memory, which copies it somewhere, you may avoid to pin them constantly. Depends on what happens once you pass control to unmanaged environment.
EDIT
Even considering interesting answer from #Brian, I would still opt for pinning the pointer. To make explicit in the code the notion of the fixed pointer, avoid any possible misguide in future code maintenance and keep clarity.

How can classes be passed by reference in .NET?

As we all know, classes in .NET are passed by reference and structs by value.
In unsafe code, you can have pointers to structs, but not to classes since they are moved by the GC. When you have a pointer to an array, for example, you either have to put it in a fixed statement (if you allocated on the heap) or stackalloc (to allocate on the stack).
With that said, how is it possible for classes to be passed by reference if they are moved by the GC?
What the GC moveth; the GC fixeth. Since the GC has to find all references to an object anyway (to see if it's GC'able), it's a small extra step to change those references to point to the new address.
You can think of class type instance as a handle, then a reference to handle would be just one more indirection (sort of a pointer to handle) limited in scope by a method call. Since the object itself remains hidden behind a handle it can be relocated without any visible effect.

How to dispose heavy set of static variable and collection?

I made a big windows app, and in the program.cs class i am using a lot to static variables
around 20 and some of these are used for big collection of object that i make during the process.
I want to know how should i mange this in the finish of application where and how should i call them dispose. I made GC.Collect but that hangs application and degrade the performance.
And when i dint call GC.Collect it was giving memory lick and hanging for long.
Please let me know how should i manage this static class, static variables. So that performance boost.
I think the way you are using the static variables is completely wrong, you might have misunderstood the concept.
You should mark any field as static only when you know, variables will be accessed through out the life of program i.e. they will be GC'ed only when you terminate the program.
EDIT In C# the memory is automatically managed by the Garbage Collector, the programmer need to know only that when an object which is created is applicable for Garbage Collection. In MSDN ducumentation it is clearly mentioned,
C# employs automatic memory management, which frees developers from manually allocating and freeing the memory occupied by objects. Automatic memory management policies are implemented by a garbage collector. The memory management life cycle of an object is as follows:
When the object is created, memory is allocated for it, the constructor is run, and the object is considered live.
If the object, or any part of it, cannot be accessed by any possible continuation of execution, other than the running of destructors, the object is considered no longer in use, and it becomes eligible for destruction. The C# compiler and the garbage collector may choose to analyze code to determine which references to an object may be used in the future. For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, the garbage collector may (but is not required to) treat the object as no longer in use.
Once the object is eligible for destruction, at some unspecified later time the destructor (Section 10.12) (if any) for the object is run. Unless overridden by explicit calls, the destructor for the object is run once only.
Once the destructor for an object is run, if that object, or any part of it, cannot be accessed by any possible continuation of execution, including the running of destructors, the object is considered inaccessible and the object becomes eligible for collection.
Finally, at some time after the object becomes eligible for collection, the garbage collector frees the memory associated with that object.
In simple words, if an object has no more live references (pointers whose scope has not ended) which are pointing to it, it is eligible for GC.
In your case the static variables are are having the scope which extends across the entire run of the program and once you remove those references either by assigning those to new objects or assigning them to null then old objects will be applicable for GC if no other live references pointing to old objects are alive.
You have IDisposable objects (Forms and Controls, I'm guessing) and need to dispose them at some appropriate time. The best way to solve this is going to be to create an object model appropriate to your domain, and have it manage them. I don't know about your domain, so it's hard to give details about that.
To make it more convenient, you could group these variables together in one class. Instead of holding these variables in the Program class, put them in another class that Program references, and make that class IDisposable. Something like this:
public class Resources : IDisposable
{
public MyForm MyForm {get;set;}
public MyControl MyControl {get;set;}
//etc...
public void Dispose()
{
if(MyForm != null)
MyForm.Dispose()
if(MyControl != null)
MyControl.Dispose()
//etc..
}
}
If the problem with this is that you want to avoid bugs around accessing Disposed objects, don't make them static! If they are not static, you can control what object bind to them more clearly, and make sure those object stop holding a reference to them when they are disposed.

Categories