As Value type variable allocates memory in Stack whereas Reference type allocates it in Heap.
So how the memory allocated when a value type variable (e.g. int i = 4;) is declared in the reference type (e.g. in a class).
How the overall memory allocation works in .NET for value type & reference type, and also value type inside the scope of reference type.
Please explain it or provide any links regarding that.
A value type variable allocates memory on the stack whereas a reference type allocates it in heap.
No, that statement is completely wrong. Lots of people believe that, but it is obviously false, as you have discovered.
How is the memory allocated when a value type variable int i = 4; is declared as a field of a reference type?
Clearly you know why your first statement is completely wrong. The integer field of the class cannot be allocated on the stack because the object might live longer than the stack frame.
To understand what is really going on, first you have to realize that there are three kinds of things:
value types
references
instances of reference type
References and instances of reference type are completely different, just as a piece of paper containing my address and my actual house are completely different.
The next thing you have to understand is that there are two kinds of storage: long-term and temporary storage. Long-term storage is usually called "the heap", but I prefer to think of it simply as long-term storage. Temporary storage is usually called "the stack" but that is also misleading because of course there could be multiple stacks, there could be temporaries stored in registers, and so on.
An instance of a reference type occupies memory in the long-term storage. (Sometimes it would be possible to determine that an instance of a reference type is short-lived, and put it in temporary storage, but we do not do this optimization in practice.)
A variable is a storage location which stores either a value of value type or a reference.
Where the storage location of the variable is allocated depends on the lifetime of the variable. If the variable is a local variable known to be of short lifetime, it is allocated from the temporary storage pool. If the variable is known to be of long lifetime (because, say, it is an outer variable of a closure) then it is allocated off the long-term storage pool.
If the variable is a field of a class, we already know that its storage comes from the long-term pool. If the variable is a field of a value type, that value type inhabits storage somewhere; the field inhabits the same storage.
If the variable is an array element, it is allocated off the long-term storage pool; arrays are instances of reference type.
The key to getting your understanding correct is to simply stop believing the myth that whether a variable is of reference or value type affects where the storage is allocated. That is not true and has never been true, and doesn't even make any sense.
The only thing that affects where a variable is stored is how long does the variable live for. Short-lived variables are allocated off the temporary pool -- the stack, or registers -- and long-lived variables are allocated off the long-term storage pool -- the heap.
This is why Eric Lippert reminds us that the stack is an implementation detail.
When an instance of a value type is a member of a reference type yes, it is stored on the managed heap along with the parent object. It's a good question and something you should understand, just not something that should drive your design in most scenarios.
structs should be small, simple data types that are relatively cheap to create and pass around. Reference types are your complex types, require only a copy of the reference to pass to a method, but of course come with some baggage due to being allocated on the heap. Here is a good follow up post regarding the implications of stack versus heap allocations.
There are plenty of references out there which explain the performance implications of value types versus reference types. You should learn all about it and also understand that, most of the time, it is a semantic decision, not a performance decision.
So how the memory allocated when a value type variable(eg int i =4;) is declared in the reference type (eg. in a class).
If the object lies on heap, it means all it's member variable(s) lies there.
here is a nice article.
BTW: not allways goes a Value on the stack - it might end in Heap.
Related
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.
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.
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).
What happen at background(in case of memory) when I declare variable and then create object for that variable . Is reference variable store anywhere and in which format and how this variable points to the memory on heap. Please clarify below doubts in the comments.
For example
ClassA instance; // Where this variable store and how much memory occupies
instance=new ClassA(); //How instance variable points to memory
EDIT
What will effect on my program memory if my program contains so many unused variable.
The instance variable is just a pointer at runtime, it points to the object allocated in the GC heap. The variable can live anywhere, stack, CPU register, inside another object that's on the heap or in the loader heap if it is static.
The big deal about the garbage collector is that it is capable of finding this pointer during a garbage collection. And can thus see that the object is still referenced and can adjust the pointer value when it compacts the heap. That's fairly straight-forward when the reference is static on inside another object. Harder when it is on the stack or a register, the jitter provides sufficient info to let the GC find it.
A reference variable is stored inline. If it's a local variable, it's allocated on the stack, if it's a member of a class it's allocated as part of the object on the heap.
An instance of a class is always allocated on the heap.
A reference is just a pointer, but what's special is that the garbage collector is aware of the reference. So, a reference uses the amount of space that a pointer uses. In a 32 bit process it uses 4 bytes, in a 64 bit process it uses 8 bytes.
The storage location of a local variable for the reference itself is platform dependent (jitters can choose where they want to store it.) Typically it will be in memory on the call stack for the method defining the local or in a CPU register. The size is also platform dependent, but is generally 4 bytes for 32-bit architecture and 8 bytes for 64-bit architecture.
The reference may or may not 'point' to the heap. It's better to think of it as an opaque reference identifier which can be used for accessing the object. The underlying pointer can change at runtime.
Regarding unused variables, the optimizing compiler will often eliminate any unused local variables entirely, so it has no impact at all on runtime performance. Also, the type of overhead you're talking about for storing a reference is miniscule for modern platforms.
If you need answers about this then I would recommend you get your hands on "CLR via C#", it is a book about how the CLR functions and it includes lots of information about this.
To answer your question, there are many things that you need to think about to answer this question.
For instance you need to store the instructions for each method in the class. When the class first loads this will effectively be a pointer to the .Net IL instructions. When the method is first needed by the application, it will be JIT compiled to actual instructions for the processor and this will be stored in memory.
Then you have static storage for class fields that will be stored only once per class.
Each class in .Net that is instantiated requires storage for various reasons, but not limited to things like inheritance, garbage collection, layout. Then you have storage for the various references that you may keep to the object which will itself take storage.
If memory is truly critical to what you are doing, then C# may not be the best choice for your application. Otherwise, just enjoy the benefits in productivity you will gain from using .NET and accept that this ease of use comes with a price of memory usage and less performance (in some cases) from a C/C++ app.
As CLRProfiler use words like HEAP statistic, OBJECTS finalized, it made me think it will atmost only show boxed struct? So what if the structs are my source of problem? How can I know about it with CLRProfiler??
According to the documentation
"CLRProfiler is a tool that is focused on analyzing what is going on in the garbage collector heap"
so naturally you'll see various statistics concerning the heap.
Structs are value types, so when they are allocated on their own, they are allocated on the stack. The stack is cleaned up during stack unwind and thus is not subject to garbage collection by the GC. If value types are boxed or more commonly if they are part of a reference type, their values will be stored on the heap.
My guess is that if a struct is a source of your problem it is because your application stores a great number of these. This is typically done using arrays (which is the underlying type of a number of .NET collections). Array is a reference type, so it is stored on the heap. If the array holds structs the values too go on the heap as part of the array instance.
In other words, if you want to inspect standalone structs during runtime, you have to locate them on the stacks of the running managed threads. To be honest I am not too familiar with CLRProfiler so I don't know if it supports that. You can, however, inspect this with debuggers such as WinDbg. If, on the other hand, the struct in question is stored in a collection, you have to locate the instance on the heap.