. NET heap in the stack

Source: Internet
Author: User
Tags garbage collection
Original source:

Although we do not need to worry about memory management and garbage collection (garbage Collection) under the. NET Framework, we should understand them to optimize our applications. At the same time, you need to have some basic knowledge of the memory management mechanism, which can help explain the behavior of variables in our daily program writing. In this article I'll explain the basics of stacks and heaps, the types of variables, and why some variables work in their own way.

In the. NET framework environment, when our code executes, there are two places in memory to store the code. If you don't know, then let me introduce you to stack (stack) and heap (Heap). Stacks and heaps are used to help us run code that resides in machine memory and contains the information required for all code execution.

* Stack vs Heap: What's the difference.

The stack is responsible for saving the path of our code execution (or invocation), while the heap is responsible for saving the object (or data, followed by a lot of questions about the heap).

You can think of stacks as a stack of boxes stacked from top to bottom. When each method is invoked, we record what is going to happen in the application in a box at the top of the stack, and we can only use the box at the top of the stack at a time. When the box at the top of our stack is used, or after the method has been executed, we will leave the box open and continue to use the new box on top of the stack. The heap works much the same way, but most of the time the heap is used to hold the information rather than save the execution path, so the heap can be accessed at any time. Compared to stacks without any access restrictions, heaps are like old clothes on the bed, we didn't take the time to sort it out because we could always find a dress we needed, and the stack was like a stacked shoe box in a locker, and we could only pick it up from the top of the box until we found the right one.

The images above are not real representations of memory but can help us distinguish between stacks and heaps.

The stack is self maintained, that is, memory automatic maintenance stack, when the top of the stack box is no longer used, it will be thrown. Instead, the heap needs to consider garbage collection, garbage collection to keep the pile tidy, no one wants to see all the dirty clothes around, it is too smelly.

* There's something in the stacks and heaps.

When our code executes, there are mainly four types of data in the stack and heap: value type, reference type (Reference type), pointer (pointer), instruction (instruction).

1. Value type:

In C #, all things declared as the following types are called value types:


2. Reference type:

All things declared to be of the following types are referred to as reference types:


3. Pointers:

The third type that is placed in a memory management scenario is a type reference, which is usually a pointer. We do not display the use of pointers that are managed by the common language runtime (CLR). A pointer (or reference) is different from a reference type because when we say something is a reference type, it means that we access it through a pointer. The pointer is a piece of memory space and it points to another memory space. Like stacks and heaps, pointers also occupy memory space, but the value is either a memory address or null.

4. Directive:

In the following article you will see how the instructions work ...

* How to decide where to put it?

Here's a golden rule:

1. Reference types are always placed in the heap. (Is it easy enough?)

2. Value types and pointers are always placed where they are declared. (This is a slightly more complex point, and you need to know how the stack works before you can determine where it was declared.) )

As we mentioned earlier, stacks are the path that is responsible for saving the execution (or invocation) of our code. When our code begins to call a method, it places an encoding instruction (in the method) onto the stack, followed by the placement of the method's arguments, and then the code executes to the variable position in the method that is "pressed" to the top of the stack. The following examples are easy to understand ...

The following is a method:
Copy C # code save code public int addfive (int pvalue)
int result;
result = Pvalue + 5;
return result;

Let's take a look at what's happening on the top of the stack and remember that we've actually pressed a lot of other content into the top of the stack we're looking at.

The first method (containing only the logical bytes to be executed, that is, the instruction that executes the method, not the data in the method body), is followed by the parameter of the method into the stack. (We'll talk more about parameter passing later)

Next, the control (that is, the thread that executes the method) is passed to the addfive () instruction on the stack.

When the method executes, we need to allocate some memory on the stack for the "result" variable,

The method finishes execution and we are returned.
Method completes, and then the result of the method is returned.

By pointing the stack pointer at the available memory address used by the addfive () method, all the memory used by the method on the stack is emptied, and the program automatically returns to the location of the original method call on the stack (not seen in this example).

In this example, our "result" variables are placed on the stack, in fact, when the value type data is declared in the method body, they are placed on the stack.

Value type data is sometimes placed on the heap. Remember this rule-value types are always placed where they are declared. Well, if a value type data is declared outside of the method body and exists in a reference type, it will be replaced by the reference type in the heap.

Look at another example:

Suppose we have such a myint class (it is a reference type because it is a class type):
Copy C # code save code public class MyInt
public int myvalue;
Then execute the following method:
Copy C # code save code Public MyInt addfive (int pvalue)
MyInt result = new MyInt ();
Result. myvalue = pvalue + 5;
return result;
As mentioned earlier, the parameters of methods and methods are placed on the stack, and then control is passed to the addfive () instruction on the stack.

Then there will be some interesting phenomena ...

Because "MyInt" is a reference type, it is placed on the heap, and a pointer reference to the heap is generated on the stack.

After the Addfive () method is executed, we will empty ...

We'll leave the lonely Myint object in the heap (there will be no pointers to myint objects in the stack!)

This is where the garbage collector (hereafter referred to as GC) works. When our program reaches a specific memory threshold and we need more heap space, the GC starts to work. The GC stops all running threads, finds all objects that exist in the heap that are no longer being accessed by the main program, and deletes them. The GC then organizes all the remaining objects in the heap to save space and adjusts all the pointers associated with those objects in the stack and in the heap. You must think that this process is very performance-intensive, so you'll know why we need to focus so much on what's in stacks and heaps, especially when it comes to writing high-performance code.

Ok... It's great when it affects me.

Good question.

When we use reference types, we are actually working with pointers to that type, not the type itself. When we use value types, we are using the value type itself. It sounds very confusing.

Again, the example is the best description.

If we execute the following methods:
Copy C # code save code public int returnvalue ()
int x = new int ();
x = 3;
int y = new int ();
y = x;
y = 4;
return x;
We're going to get a value of 3, very simple, right.

If we first use the Myint class
Copy C # code save code public class MyInt
public int myvalue;
Then execute the following methods:
Copy C # code save code public int ReturnValue2 ()
MyInt x = new MyInt ();
X.myvalue = 3;
MyInt y = new MyInt ();
y = x;
Y.myvalue = 4;
return x.myvalue;
What we're going to get.    ... 4!

Why. ... how did X.myvalue become 4?  ... Look at what we've done and then we'll know what's going on:

In the first example, everything goes as planned:
Copy C # code save code public int returnvalue ()
int x = 3;
int y = x;
y = 4;
return x;

In the second example, we don't get "3" because both the variable "x" and "Y" point to the same object in the heap.
Copy C # code save code public int ReturnValue2 ()
MyInt x;
X.myvalue = 3;
MyInt y;
y = x;
Y.myvalue = 4;
return x.myvalue;

Hopefully, this will give you a better understanding of the basic differences between value types and reference types in C #, and have a basic understanding of when pointers and pointers are used.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.