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.
Related
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.
Let's say a class instance will build arrays:
class FooArrBuilder
{
public Foo[] FinalResult { get { return arr; } }
Foo[] arr;
public void BuildArr();
...
}
Then it's used like this:
Foo[] GetFooArr()
{
var fb = new FooArrBuilder();
fb.BuildArr();
...
return fb.FinalResult;
}
When an array is built inside an instance local to a function, will the array be moved out of the instance that built it, or will the whole instance be kept in memory just to contain the array? I do not necessarily want to copy the array if the latter is the case - but maybe I could make the class a struct? Help is appreciated :)
If you care to elaborate a bit on C#'s memory model here, it would probably help me to avoid further confusion as well.
Thanks in advance
The class instance does not "own" or "contain" the array. It merely references the array, which is allocated on the heap. Other references to that array will not keep instances of that class alive.
If any other objects (or stack frames) refer to that array, the memory on the heap that is allocated for the array will stay allocated for that array. Once those objects are garbage collected and those stack frames get popped, the garbage collector will claim the memory allocated for that array.
Yes, it would be. As long as array items of type Foo doesn't hold reference to FooArrBuilder
I think I understand now.
When the FooArrBuilder is instantiated, it is done so on the heap.
A pointer to it, the size of an int, is put on the stack.
The reference count to the object allocated on the heap is increased by one.
When the instance of FooArrBuilder creates the array, ALMOST the same process happens for the array; a heap object is once again allocated with reference count 1, this time of type Foo[]. However, this time, no pointer is put on the stack - instead, inside the memory pointed to by the stack pointer we retrieved earlier, the Foo[] arr, which is actually a pointer to a Foo[] object, is set to point to the new array.
When we're about to return, we retrieve another reference to the Foo[], called arr, from the instance. The reference count for the array is now 2.
When the function then returns, the reference to the class instance is lost, and so the reference count is now 0. Therefore the instance is marked as garbage. When the instance is (at some indeterminate point) later garbage collected, the reference it had to the array is lost - and so then the array's reference count is once again 1.
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.
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++]
I have been trying to figure out the intricacies of the .NET garbage collection system and I have a question related to C# reference parameters. If I understand correctly, variables defined in a method are stored on the stack and are not affected by garbage collection. So, in this example:
public class Test
{
public Test()
{
}
public int DoIt()
{
int t = 7;
Increment(ref t);
return t;
}
private int Increment(ref int p)
{
p++;
}
}
the return value of DoIt() will be 8. Since the location of t is on the stack, then that memory cannot be garbage collected or compacted and the reference variable in Increment() will always point to the proper contents of t.
However, suppose we have:
public class Test
{
private int t = 7;
public Test()
{
}
public int DoIt()
{
Increment(ref t);
return t;
}
private int Increment(ref int p)
{
p++;
}
}
Now, t is stored on the heap as it is a value of a specific instance of my class. Isn't this possibly a problem if I pass this value as a reference parameter? If I pass t as a reference parameter, p will point to the current location of t. However, if the garbage collector moves this object during a compact, won't that mess up the reference to t in Increment()? Or does the garbage collector update even references created by passing reference parameters? Do I have to worry about this at all? The only mention of worrying about memory being compacted on MSDN (that I can find) is in relation to passing managed references to unmanaged code. Hopefully that's because I don't have to worry about any managed references in managed code. :)
If I understand correctly, variables defined in a method are stored on the stack and are not affected by garbage collection.
It depends on what you mean by "affected". The variables on the stack are the roots of the garbage collector, so they surely affect garbage collection.
Since the location of t is on the stack, then that memory cannot be garbage collected or compacted and the reference variable in Increment() will always point to the proper contents of t.
"Cannot" is a strange word to use here. The point of using the stack in the first place is because the stack is only used for data which never needs to be compacted and whose lifetime is always known so it never needs to be garbage collected. That why we use the stack in the first place. You seem to be putting the cart before the horse here. Let me repeat that to make sure it is clear: the reason we store this stuff on the stack is because it does not need to be collected or compacted because its lifetime is known. If its lifetime were not known then it would go on the heap. For example, local variables in iterator blocks go on the heap for that reason.
Now, t is stored on the heap as it is a value of a specific instance of my class.
Correct.
Isn't this possibly a problem if I pass this value as a reference parameter?
Nope. That's fine.
If I pass t as a reference parameter, p will point to the current location of t.
Yep. Though the way I prefer to think of it is that p is an alias for the variable t.
However, if the garbage collector moves this object during a compact, won't that mess up the reference to t in Increment()?
Nope. The garbage collector knows about managed references; that's why they're called managed references. If the gc moves the thing around, the managed reference is still valid.
If you had passed an actual pointer to t using unsafe code then you would be required to pin the container of t in place so that the garbage collector would know to not move it. You can do that using the fixed statement in C#, or by creating a GCHandle to the object you want to pin.
does the garbage collector update even references created by passing reference parameters?
Yep. It would be rather fragile if it didn't.
Do I have to worry about this at all?
Nope. You're thinking about this like an unmanaged C++ programmer -- C++ makes you do this work, but C# does not. Remember, the whole point of the managed memory model is to free you from having to think about this stuff.
Of course, if you enjoy worrying about this stuff you can always use the "unsafe" feature to turn these safety systems off, and then you can write heap and stack corrupting bugs to your heart's content.
No, you don't need to worry about it. Basically the calling method (DoIt) has a "live" reference to the instance of Test, which will prevent it from being garbage collected. I'm not sure whether it can be compacted - but I suspect it can, with the GC able to spot which variable references are part of objects being moved.
In other words - don't worry. Whether it can be compacted or not, it shouldn't cause you a problem.
It is exactly how you mention it in the last sentence. The GC will move all needed references when it compacts the heap (except for references to unmanaged memory).
Note that using the stack or heap is related to an instance variable being of a value or reference type. Value types (structs and 'simple' types like int, double, etc) are always on the stack, classes are always in the heap (what is in the stack is the reference - the pointer - to the allocated memory for the instance).
Edit: as correctly noted below in the comment, the second paragraph was written much too quickly. If a value type instance is a member of a class, it will not be stored in the stack, it will be in the heap like the rest of the members.