Stack and Heap memory effects? - c#

In the following code:
MyClass oMyClass1;
MyClass oMyClass2 = null;
My doubt is how the above two lines will affect memory (stack & heap).
Will create reference in stack?

my doubt is how the above two lines will affect memory(stack & heap).
Insufficient information, 2 possibilities:
they are local variables. In that case those 2 lines make 2 identical allocations (of a reference, always 32/64 bits) on the stack (whenever and for how long the method is executed). No allocations on the heap.
they are fields in a class or struct. In that case those 2 lines each allocate the size of a reference in the instance when it is created. That instance could be allocated on the stack (when they are struct members) or on the heap (class members).

Strictly speaking, it depends on where the code is.
If the code is in a regular function/method, it will affect the stack only. There will be no effect on the heap, because no MyClass objects have been constructed yet.
Assuming MyClass is a class (i.e. reference type), the declarations will each reserve enough space on the stack to hold a reference to a MyClass object.
The two declarations are slightly different - the first one has not been initialised, so any attempt to access oMyClass1 before it is set to something will give a compiler error. The second one is initialised, so you will not get a compiler error [although you will get a runtime error if you access a method or property of oMyClass2 before you set it to refer to an actual object, e.g. with oMyClass2 = new MyClass();].
If the code is inside a class declaration:
class Fred {
MyClass oMyClass1;
MyClass oMyClass2 = null;
}
then it will only be executed during the Fred constructor. The space (for a Fred object, including space for two MyClass references) will already have been allocated on the heap before the constructor is called. The two lines of code will actually have no effect, as the space will already have been initialised to null.
If it is inside a struct declaration, the effect will be similar, only on the stack (if the struct is local) or global variable memory (if the struct is static). [Although, to be fair, I'm a tiny bit unsure where statics get allocated in C# - I am just assuming it is done in a similar way to C++]

Related

Where object will contained if it will be local [duplicate]

I am getting confused with memory allocation basics between Stack vs Heap. As per the standard definition (things which everybody says), all Value Types will get allocated onto a Stack and Reference Types will go into the Heap.
Now consider the following example:
class MyClass
{
int myInt = 0;
string myString = "Something";
}
class Program
{
static void Main(string[] args)
{
MyClass m = new MyClass();
}
}
Now, how does the memory allocation will happen in c#? Will the object of MyClass (that is, m) will be completely allocated to the Heap? That is, int myInt and string myString both will go to heap?
Or, the object will be divided into two parts and will be allocated to both of the memory locations that is, Stack and Heap?
You should consider the question of where objects get allocated as an implementation detail. It does not matter to you exactly where the bits of an object are stored. It may matter whether an object is a reference type or a value type, but you don't have to worry about where it will be stored until you start having to optimize garbage collection behavior.
While reference types are always allocated on the heap in current implementations, value types may be allocated on the stack -- but aren't necessarily. A value type is only allocated on the stack when it is an unboxed non-escaping local or temporary variable that is not contained within a reference type and not allocated in a register.
If a value type is part of a class (as in your example), it will end up on the heap.
If it's boxed, it will end up on the heap.
If it's in an array, it will end up on the heap.
If it's a static variable, it will end up on the heap.
If it's captured by a closure, it will end up on the heap.
If it's used in an iterator or async block, it will end up on the heap.
If it's created by unsafe or unmanaged code, it could be allocated in any type of data structure (not necessarily a stack or a heap).
Is there anything I missed?
Of course, I would be remiss if I didn't link to Eric Lippert's posts on the topic:
The Stack Is An Implementation Detail, Part One
The Stack Is An Implementation Detail, Part Two
And perhaps the best one: The Truth About Value Types
m is allocated on the heap, and that includes myInt. The situations where primitive types (and structs) are allocated on the stack is during method invocation, which allocates room for local variables on the stack (because it's faster). For example:
class MyClass
{
int myInt = 0;
string myString = "Something";
void Foo(int x, int y) {
int rv = x + y + myInt;
myInt = 2^rv;
}
}
rv, x, y will all be on the stack. myInt is somewhere on the heap (and must be access via the this pointer).
"All VALUE Types will get allocated to Stack" is very, very wrong; struct variables can live on the stack, as method variables. However, fields on a type live with that type. If a field's declaring type is a class, the values are on the heap as part of that object. If a field's declaring type is a struct, the fields are part of that struct where-ever that struct lives.
Even method variables can be on the heap, if they are captured (lambda/anon-method), or part of (for example) an iterator block.
Excellent explanation:
Part1: http://www.c-sharpcorner.com/uploadfile/rmcochran/csharp_memory01122006130034pm/csharp_memory.aspx
Part 2: http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx
Part 3: http://www.c-sharpcorner.com/UploadFile/rmcochran/chsarp_memory401152006094206AM/chsarp_memory4.aspx
Part 4: http://www.c-sharpcorner.com/uploadfile/rmcochran/csharp_memory_401282006141834pm/csharp_memory_4.aspx
Stack
The stack is a block of memory for storing local variables and parameters. The stack logically grows and shrinks as a function is entered and exited.
Consider the following method:
public static int Factorial (int x)
{
if (x == 0)
{
return 1;
}
return x * Factorial (x - 1);
}
This method is recursive, meaning that it calls itself. Each time the method is entered, a new int is allocated on the stack, and each time the method exits, the int is deallocated.
Heap
The heap is a block of memory in which objects (i.e., reference-type instances) reside. Whenever a new object is created, it is allocated on the heap, and a reference to that object is returned. During a program’s execution, the heap starts filling up as new objects are created. The runtime has a garbage collector that periodically deallocates objects from the heap, so your program does not run Out Of Memory. An object is eligible for deallocation as soon as it’s not referenced by anything that’s itself alive.
The heap also stores static fields. Unlike objects allocated on the heap (which can get garbage-collected), these live until the application domain is torn down.
Consider the following method:
using System;
using System.Text;
class Test
{
public static void Main()
{
StringBuilder ref1 = new StringBuilder ("object1");
Console.WriteLine (ref1);
// The StringBuilder referenced by ref1 is now eligible for GC.
StringBuilder ref2 = new StringBuilder ("object2");
StringBuilder ref3 = ref2;
// The StringBuilder referenced by ref2 is NOT yet eligible for GC.
Console.WriteLine (ref3); // object2
}
}
In the above example, we start by creating a StringBuilder object referenced by the variable ref1, and then write out its content. That StringBuilder object is then immediately eligible for garbage collection, because nothing subsequently uses it. Then, we create another StringBuilder referenced by variable ref2, and copy that reference to ref3. Even though ref2 is not used after that point, ref3 keeps the same StringBuilder object alive—ensuring that it doesn’t become eligible for collection until we’ve finished using ref3.
Value-type instances (and object references) live wherever the variable was
declared. If the instance was declared as a field within a class type, or as an array element, that instance lives on the heap.
simple measures
Value type can be stred on THE STACK ,it is the implementaional detail it can be allocated to the some futuristist data structure.
so, it is better to understand how value and reference type works , Value type will be copied by value that means when you pass a value type as a param to a FUNCTION than it will be copied by nature means you will have a total new copy.
Reference types are passed by reference ( againg do not consider reference will store a address again in some future versions ,it may be stored on some other data structures.)
so in your case
myInt is a int which is ecapsulated in a class which offcourse an reference type so it will be tied to the instance of the class which will be stored on 'THE HEAP'.
i would suggest , you can start reading blogs written by ERIC LIPPERTS.
Eric's Blog
Each time an object is created in it goes into the area of memory known as heap. The primitive variables like
int and double are allocated in the stack, if they are local method variables and in the heap if they are member
variables . In methods local variables are pushed into stack when a method is invoked
and stack pointer is decremented when a method call is completed. In a multithreaded application each thread
will have its own stack but will share the same heap. This is why care should be taken in your code to avoid any
concurrent access issues in the heap space. The stack is threadsafe (each thread will have its own stack) but the
heap is not thread safe unless guarded with synchronisation through your code.
This link is also useful http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/
m is a reference to an object of MyClass so m is stores in the stack of main thread but the object of MyClass stores in the heap. Therefore myInt and myString store in the heap.
Note that m is only a reference (an address to memory) and is on main stack. when m deallocated then GC clear the MyClass object from the heap
For more detail read all four parts of this article
https://www.c-sharpcorner.com/article/C-Sharp-heaping-vs-stacking-in-net-part-i/
As per the standard definition (things which everybody says), all Value Types will get allocated onto a Stack and Reference Types will go into the Heap.
This is wrong. Only local (in the context of a function) value types/arrays of value types are allocated on the stack. Everything else is allocated on the heap.

Does just declaring a variable of a simple type allocates memory?

I read this question in C, and I have the same question in C#.
Is it correct to say that by the code
int a;
four unassigned bytes is reserved for a before it is initialized? Or initialization is where the bytes are allocated for the first time?
An int declaration without assignment will (as mentioned in the comments) will be optimized away by the compiler- it will not show up at all in the program.
Assuming you are in a function (as opposed to a type definition) and assign the int, the allocation will take place from stack space when the function begins (that is, the int is allocated from memory already dedicated to that thread, and will not result in a OS allocation).
On the other hand, if the int is part of a type definition (and is used) then it will increase the allocated space of each instance of that type, wherever that type ends up being allocated (heap for classes, heap or stack for structs depending on usage).
In no situation will it result in a pointer or reference for the int itself.
Some further explanation:
Th original question refers to an int by example. An int is a fixed-length (4-byte) data structure, so the compiler notes that the method containing the declaration in question will be needing 4 bytes to store it. Rather than allocating those 4 bytes on the heap (where it puts reference types) and incurring garbage collection overhead, the compiler will reserve 4 bytes in the area of memory reserved for the current thread's method local variables (the call stack). That memory had been allocated from the OS when the thread started and it is reserved for that thread alone. If the thread runs out of that space, it's called a stack overflow.
It's worth noting here that .NET really has 2 compilers- the C# compiler that converts C# code into IL, and the JIT compiler that converts IL into machine instructions at runtime. In my answer when I say "the compiler", I am doing some hand-waving about which compiler I mean exactly, but the result is the same.
As per the comments, if I do this...
void Foo() {
{
int a = 5;
Console.WriteLine(a);
}
{
int a = 7;
Console.WriteLine(a);
}
}
... then it is possible that the compiler could re-use the stack space allocated for the first variable a for the second, as they are semantically different. But that's an optimization.
It's also worth noting that the call stack includes other information besides method-local variables- it includes the parameters to the method, space for the return value (a pointer if the function returns a reference type), and the return address as well.
Finally, I'd add that in C# your methods may be inlined by the JIT compiler- this means that the code of a called method may be copied wholesale into the body of the caller to avoid the overhead of a method call. In that case, the stack frame will include space for the called method's local variables as well.
An int in C# is always 4 bytes (no matter what the value).
Remember that
int a;
is the same as
int a = 0;
When declaring an int, it is given the default value of 0.
Well, It depends on the variable type.
Since int is a ValueType it allocates all 4 bytes needed.
There are two main categories of variables in c# : Reference Types and Value Types.In case of value Types such as int all the memory needed for the variable allocates but when you declare a variable of a reference type before using new operator it just allocates a pointer and after creating the main object it allocates the space needed for storing the variable.
Class MyType
{
...
}
MyType s; // Just a pointer
s=new MyType(); //Now allocating happens.
For more information on Reference Types see MSDN Reference Types.
For more information on Value Types see MSDN Value Types.
MSDN :
There are two kinds of types in C#: reference types and value types.
Variables of reference types store references to their data (objects),
while variables of value types directly contain their data. With
reference types, two variables can reference the same object;
therefore, operations on one variable can affect the object referenced
by the other variable. With value types, each variable has its own
copy of the data, and it is not possible for operations on one
variable to affect the other (except in the case of ref and out
parameter variables, see ref (C# Reference) and out parameter modifier
(C# Reference)).
A simple declaration of a variable like in your example will contain a reference, until you create an object with new keyword.

Reference type in struct in C#

I was going through type values in C# and learned that they don't get allocated on the heap as normal reference types do. How does a struct with reference type get allocated?
e.g.
struct simple{
public Employee e;
public bool topEmployee;
public void printSomething()
{
Console.WriteLine("Progress " + e.GetProgressReport());
Console.WriteLine("TopEmployee " + topEmployee);
}
};
The Employee is a class. Will e get allocated to a heap when initialized? Does it defeat the point of having a struct?
The "kind" of type (value/reference) has little to do with how instances are allocated. It's all about life time, and there are more ways to allocate than "heap" and "stack". Read The Truth About Value Types.
But insofar your question makes sense: A struct's member types do not affect how struct instances are allocated, because they do not affect the lifetime of the object. Same goes for classes, by the way.
The member e will be a part of the value type object and allocated where it may be. This member is a reference, and hence any actual Employee object e refers to will be allocated somewhere else1. Though it sounds like one, this is not a special rule; locals and class members and array items behave the same way. It does not defeat the point of value types, rather maintains the benefits of both value and reference types. The value type instances are still separate values instead of being aliased, and they still have simpler and shorter life time allowing better allocation choices with less effort. The reference type instances are still shared and (potentially) long-lived.
1 At least conceptually and in the current implementations; in very simple cases optimizations (escape analysis+allocation sinking) could merge these allocations, but no CLR I'm aware of does that.
Struct memory is allocated 'in-line'. Class memory is allocated on the heap, with a reference (pointer) allocated 'in-line'.
If you see a class variable named C in a program, the storage for that variable will be equivalent to a pointer (say 4 bytes), and the actual storage for the class will be on the heap.
But if you see a struct variable named S in a program, the storage for that variable is simply the size of the variable at the point of declaration. There is no heap allocated storage for it.
If C contains an S then S will be located in the heap storage for C.
If S contains a C then the reference to C will be located in the storage for S, and the storage for C is on the heap. This is the answer to your question about simple and e.
So struct storage can actually be in static memory, on the stack or on the heap (inside a class). Class memory is always on the heap.
The reference variable 'e' will be allocated wherever the struct is allocated (e.g. a local variable of unboxed struct type is likely to go on stack). The instance of Employee the 'e' is pointing to will be allocated on heap. This may vary between .NET implementations, but is most likely true for all current implementations.

Is it true that - Garbage Collector won't collection the object of struct type

Yesterday, we had a discussion on Gargbage collection.
It was discussed that the objects created using Classes are collected by Garbage collector, but it cannot be collected by GC if it is being created using struct
I know that structures uses stack and classes uses heap.
But, I guess GC never collects unmanaged codes only. So does that mean that the Structure types are unmanaged code. (I don't think so).
OR is it that the GC take care of Heap only and not Stack?
If yes, then what about int data type. int is struct not class. So if we defined the object of type int, isn't it managed by GC?
The GC will collect any managed objects (and Structures are managed objects) if they cannot be accessed from a GC root.
but it cannot be collected by GC, if it is being created using struct.
What you were told is incorrect. It doesn't matter how a managed object was created - if there are no references to it anymore, it will end up being collected.
OR is that means the GC take care of Heap only not Stack?
The GC takes care of the object graph - if objects are reachable by any of the GC roots, they will not be collected, if they are not, they will end up being collected. The Stack and Heap are not relevant.
So if we defined the object of type int, isn't it managed by GC?
int (AKA System.Int32) is a managed object - a structure. If you declare an int field in a class and the class goed out of scope, the int will end up being collected by the GC, for example.
As #leppie commented, in many situations, structures will get placed on the stack and when the stack is popped they will no longer exist - the GC, in such cases, is not involved (and doesn't need to be).
it cannot be collected by GC if it is being created using struct.
Not true. If it's not referenced it will be collected eventually.
I know that structures use stack and classes use heap.
That is a common misconception. See this Lippert's article for details.
I think that the idea you're referencing to is that most often GC does not bother with collecting any data located on stack, because stack will be destroyed as soon as program execution leaves its scope. So that means that any data put directly into stack (which might mean value types and should mean references to all the other data) will be cleared automatically, no need to use GC. GC's work is to clear heap data independently of its (data) type. If it's not referenced - it's collected.
But, I guess GC never collects unmanaged codes only. So is that means the Structure types are unmanaged code. (I don't think so).
I don't understand what you are asking here.
OR is that means the GC take care of Heap only not Stack?
Yes and No. GC takes care of memory required for instances of reference types (always created on the managed heap). You can view the "stack" as a piece of memory associated with current thread of execution. The stack can contain handles to reference types allocated on the managed heap. In this case the GC "cares": it will not collect the memory from the managed heap for these instances until these references on the stack exist. The stack can also contain instances (not references to!) of value types, in which case the GC does not care...
If yes, then what about int data type. int is struct not class. So if we defined the object of type int, isn't it managed by GC?
This question is a bit misleading. Let's say you "allocate" an instance of an int on the stack:
void Foo()
{
// ...
int tTmp;
//...
}
In this case the GC does not care about tTmp. It is placed on the current thread's stack and removed, if it gets out of scope. But if you do this:
void Foo()
{
//...
var tTmp = new int [] {
1, 2, 3, 4
};
//...
}
then the array of 4 integers is created on the managed heap and GC takes care of tTmp. It also "indirectly" takes care of the memory required for the contents of the array, which happen to be the space required for the four integers...
Let's see what the .NET standard (ECMA-334) says
Value types differ from reference types in that variables of the value
types directly contain their data, whereas variables of the reference
types store references to their data, the latter being known as
objects. With reference types, it is possible for two variables to
reference the same object, and thus possible for operations on one
variable to affect the object referenced by the other variable. With
value types, the variables each have their own copy of the data, and
it is not possible for operations on one to affect the other.
In other words, there is no reason for garbage collector to care about value types, because they clean-up after themselves (when they go out of scope), they contain their own data. GC is for clean-up of shared (references) data.
Note that not only structures are value types:
A value type is either a struct type or an enumeration type. C#
provides a set of predefined struct types called the simple types. The
simple types are identified through reserved words.
So e.g. "int" type is so called "simple type", value type. It is bit different from other structures, because operations like +-*/ could end up being compiled into primitive operations, not function calls.

Why are structs stored on the stack while classes get stored on the heap(.NET)?

I know that one of the differences between classes and structs is that struct instances get stored on stack and class instances(objects) are stored on the heap.
Since classes and structs are very similar. Does anybody know the difference for this particular distinction?
(edited to cover points in comments)
To emphasise: there are differences and similarities between value-types and reference-types, but those differences have nothing to do with stack vs heap, and everything to do with copy-semantics vs reference-semantics. In particular, if we do:
Foo first = new Foo { Bar = 123 };
Foo second = first;
Then are "first" and "second" talking about the same copy of Foo? or different copies? It just so happens that the stack is a convenient and efficient way of handling value-types as variables. But that is an implementation detail.
(end edit)
Re the whole "value types go on the stack" thing... - value types don't always go on the stack;
if they are fields on a class
if they are boxed
if they are "captured variables"
if they are in an iterator block
then they go on the heap (the last two are actually just exotic examples of the first)
i.e.
class Foo {
int i; // on the heap
}
static void Foo() {
int i = 0; // on the heap due to capture
// ...
Action act = delegate {Console.WriteLine(i);};
}
static IEnumerable<int> Foo() {
int i = 0; // on the heap to do iterator block
//
yield return i;
}
Additionally, Eric Lippert (as already noted) has an excellent blog entry on this subject
It's useful in practice to be able to allocate memory on the stack for some purposes, since those allocations are very fast.
However, it's worth noting that there's no fundamental guarantee that all structs will be placed on the stack. Eric Lippert recently wrote an interesting blog entry on this topic.
Every process has a data block consists of two different allocatable memory segment. These are stack and heap. Stack is mostly serving as the program flow manager and saves local variables, parameters and returning pointers (in a case of returning from the current working function).
Classes are very complex and mostly very large types compared to value types like structs (or basic types -- ints, chars, etc.) Since stack allocation should be specialized on the efficiency of program flow, it is not serving an optimal environment to keep large objects.
Therefore, to greet both of the expectations, this seperated architecture came along.
How the compiler and run-time environment handle memory management has grown up over a long period of time. The stack memory v.s. heap memory allocation decision had a lot to do with what could be known at compile-time and what could be known at runtime. This was before managed run times.
In general, the compiler has very good control of what's on the stack, it gets to decide what is cleaned up and when based on calling conventions. The heap on the other hand, was more like the wild west. The compiler did not have good control of when things came and went. By placing function arguments on the stack, the compiler is able to make a scope -- that scope can be controlled over the lifetime of the call. This is a natural place to put value types, because they are easy to control as opposed to reference types that can hand out memory locations (pointers) to just about anyone they want.
Modern memory management changes a lot of this. The .NET runtime can take control of reference types and the managed heap through complex garbage collection and memory management algorithms. This is also a very, very deep subject.
I recommend you check out some texts on compilers -- I grew up on Aho, so I recommend that. You can also learn a lot about the subject by reading Gosling.
In some languages, like C++, objects are also value types.
To find an example for the opposite is harder, but under classic Pascal union structs could only be instantiated on the heap. (normal structs could be static)
In short: this situation is a choice, not a hard law. Since C# (and Java before it) lack procedural underpinnings, one can ask themselves why it needs structures at all.
The reason it is there, is probably a combination of needing it for external interfaces and to have a performant and tight complex (container-) type. One that is faster than class. And then it is better to make it a value type.
Marc Gravell already explained wonderfully the difference regarding how value and reference types are copied which is the main differentiation between them.
As to why value types are usually created on the stack, that's because the way they are copied allows it. The stack has some definite advantages over the heap in terms of performance, particularly because the compiler can calculate the exact position of a variable created in a certain block of code, which makes access faster.
When you create a reference type you receive a reference to the actual object which exists in the heap. There is a small level of indirection whenever you interact with the object itself. These reference types cannot be created on the stack because the lifetime of values in the stack is determined, in great part, by the structure of your code. The function frame of a method call will be popped off the stack when the function returns, for example.
With value types, however, their copy semantics allows the compiler, depending on where it was created, to place it in the stack. If you create a local variable that holds an instance of a struct in a method and then return it, a copy of it will be created, as Marc explained above. This means that the value can be safely placed in the stack, since the lifetime of the actual instance is tied to the method's function frame. Anytime you send it somewhere outside the current function a copy of it will be created, so it doesn't matter if you tie the existence of the original instance to the scope of the function. Along these lines, you can also see why value types that are captured by closures need to go in the heap: They outlive their scope because they must also be accessible from within the closure, which can be passed around freely.
If it were a reference type, then you wouldn't be returning a copy of the object, but rather a reference, which means the actual value must be stored somewhere else, otherwise, if you returned the reference and the object's lifetime was tied to the scope in which it was created, it would end up pointing to an empty space in memory.
The distinction isn't really that "Value types go on the stack, reference types on the heap". The real point is that it's usually more efficient to access objects that live in the stack, so the compiler will try and place those values it can there. It simply turns out that value types, because of their copy semantics, fit the bill better than reference types.
I believe that whether or not to use stack or heap space is the main distinction between the two, perhaps this article will shed some light on your question: Csharp classes vs structs
The main difference being that the heap may hold objects that live forever while something on the stack is temporary in that it will disappear when the enclosing callsite is exited. This is because when one enters a method it grows to hold local variables as well as the caller method. When the method exits (ab)normally eg return or because of exception each frame must be popped off the stack. Eventually the interested frame is popped and everything on it lost.
The whole point about using the stack is that it automatically implements and honours scope. A variable stored on the stack exists until the functiont that created it exits and that functions stack frame is popped. Things that have local scope are natural for stack storage things that have bigger scope are more difficult to manage on the stack. Objects on the heap can have lifetimes that are controlled in more complex ways.
Compilers always use the stack for variables - value or reference it makes little difference. A reference variable doesn't have to have its value stored on the stack - it can be anywhere and the heap makes a more efficient if the object referenced is big and if there are multiple references to it. The point is that the scope of a reference variable isn't the same as the lifetime of the object it references i.e. a variable may be destroyed by being popped off the stack but the object (on the heap) it references might live on.
If a value type is small enough you might as well store it on the stack in place of a reference to it on the heap - its lifetime is tied to the scope of the variable. If the value type is part of a larger reference type then it too could have multiple references to it and hence it is more natural to store it on the heap and dissociate its lifetime from any single reference variable.
Stack and heap are about lifetimes and the value v reference semantics is almost a by product.
Have a look at Value and Reference
Value types go on the stack, reference types go on the heap. A struct is a value type.
There is no guaruantee about this in the specification though, so it might change in future releases:)

Categories

Resources