ArticleDirectory
- Value Type:
- Reference Type:
- Pointer:
- Command:
In. net, we may not have to worry about memory management and garbage collection GC, but we should understand these things to optimize us as necessary.ProgramPerformance. In addition, if you have an understanding of how memory management works, it will help explain the running rules of each variable in each program. This article mainly explains heap and stack, various variables, and how these variables work.
. NET Framework is being executedCodeThere are two places to store objects, namely the heap and stack, to help execute our code. They reside in the machine memory and contain all the information we need to implement.
Stack vs heap
Stacks are more or less used to track what is being executed in your code, or called what is in the code. The heap is more or less used to track our objects or data. In most cases, it is data.
Think of the stack as a stacked box from top to bottom. Every time we call a method, we add a new box to the top of the stack. We use this method to track what our program is running. What we can use is always the top box. When we use this box at the top, that is, when the method is executed and the result is returned, we will kill and throw it! Then process the stuff in the next box. The heap is actually similar, except that it is used to save information (not to track program execution in most cases), so everything in the heap can be accessed without restrictions. The heap is like the laundry we don't have to clean up on the bed. We can quickly pick up any piece of clothing. The stack is like a box with a pile of shoes in the closet. We have to take them one by one from the top to get the next pair of shoes.
Although it is not the real memory stack, it helps us understand their differences.
Stack is "self-maintained", meaning that it basically manages its own memory (rather than elsewhere. When the top box is not in use, it will be thrown (it is not your own snow )! The heap is not the same. It must deal with GC. This is used to ensure that the heap is clean (there is not too much garbage memory. (Some people like to put a pile of dirty clothes on the ground! Stinking !).
What goes on the stack and heap?
When the code is executed, four types of stuff are placed in the stack: Value Type, reference type, pointer (pointers), and instruction (instructions ).
Value Type:
In C #, the value type is inherited from system. valuetype:
Bool, byte, Char, decimal, double, Enum, float, Int, long, sbyte, short, struct, uint, ulong, ushort
Reference Type:
The reference types include:
Class, interface, Delegate, object, string
Pointer:
The third type of reference in the memory management model. This reference usually refers to a pointer. We cannot directly use pointers, which are managed by CLR. The pointer is different from the reference type. When we say that XX is a reference type, it actually means that we need to access the value of this type through the pointer. A pointer occupies one space in the memory and only wants another space in the memory. Like anything else in the stack, pointers occupy physical space. Its value is either null or memory address.
Command:
I will explain it again in subsequent articles ......
How is it decided what goes where? (Huh ?)
Okok. Let's talk about the stack.
There are two gold rules:
- The reference type is always stored in the heap-clear enough
- The value type and pointer are always stored in the declared position. A little more complicated, because you need to understand what is "where it is declared"
Stack, as we mentioned earlier, is responsible for tracking where a single thread runs. You may think of it as a thread state machine. Each thread has its own stack. When our code calls a method, the thread starts to execute the JIT compiled Instruction Set and save it in the method table. At the same time, it pushes the method parameter into the thread stack. Then, execute the code and access the variables required in the method that already exist at the top of the thread stack. For example:
Public IntAddfive (IntPvalue)
{
IntResult;
Result = pvalue + 5;
ReturnResult;
}
Let's take a look at what happened in the stack. Remember that we only see things at the top of the stack. There have been countless other things in it!
When we start to execute this method, the method parameters are pushed to the stack (we will discuss parameter transfer later ).
Notice: The method does not exist in the stack. The legend is only used to demonstrate the concept.
Next, the control (thread executes this method) is handed over to the instruction set of the addfive method in the method table. If this is the first time this method is used, JIT compilation will be executed.
During method execution, we need memory to save the "result", so the stack top allocates space for it.
The method is complete and result is returned.
At this time, the top pointer of the stack will be moved to the memory address starting with the initial addfive method, so that all the memory space allocated just now will be cleared, then execute the addfive function below (shown in the figure ).
In this example, the result variable is pushed to the stack. In fact, value variables are declared inside the method at any time, and the stack is pressed.
However, value variables are sometimes stored in the heap. Let's look at Rule 2. The value type is always stored in the declared place. If the value type is declared outside the method and exists inside the reference type, it will be saved in the heap.
In the following example:
If we have Myint class (reference type ):
Public ClassMyint
{
Public IntMyvalue;
}
Another method is being executed:
PublicMyint addfive (IntPvalue)
{
Myint result =NewMyint ();
Result. myvalue = pvalue + 5;
ReturnResult;
}
As with the previous header, the thread starts to execute the method, and the parameter is pushed to the stack:
Now it's fun:
Because Myint is a reference type, it is stored in the heap and referenced through the pointer in the stack.
After addfive is executed, we start to clear the top of the stack:
In this way, we leave the Myint object in the heap as an orphan, because there is no pointer in the stack to reference it!
This is the time for GC to show off! GC starts when our program reaches a specific memory threshold (threshold) and we need more heap space. GC completely stops all running threads, finds objects not referenced in all stacks, and then deletes them like fallen leaves. GC re-organizes all objects that are stranded in memory and adjusts the addresses referenced in the stack. We can see that from the performance perspective, this is really time-consuming. So now, do you think that stack processing will help you write high-performance code?
Okay, okay. It's great. But how can this thing torture us?
Good question.
When we use the reference type, we actually use a pointer to this object, not the object itself. When we use the value type, we use the value itself. Clear or not?
It is better to give an example.
If we do the following:
Public IntReturnvalue ()
{
IntX =New Int();
X = 3;
IntY =New Int();
Y = X;
Y = 4;
ReturnX;
}
We get 3, which is simple enough.
If so:
Public ClassMyint
{
Public IntMyvalue;
}
Public IntReturnvalue2 ()
{
Myint x =NewMyint ();
X. myvalue = 3;
Myint y =NewMyint ();
Y = X;
Y. myvalue = 4;
ReturnX. myvalue;
}
Then we will get 4.
Why?
In the first example, everything follows the schedule:
Public IntReturnvalue ()
{
IntX = 3;
IntY = X;
Y = 4;
ReturnX;
}
In the following example, we cannot get 3 because both X and Y point to the same object in the heap.
Public IntReturnvalue2 ()
{
Myint X;
X. myvalue = 3;
Myint y;
Y = X;
Y. myvalue = 4;
ReturnX. myvalue;
}
We hope this article will help you better understand the basic differences between the value type and the reference type, as well as what the pointer is and when it will be used. In the subsequent series, we will further elaborate on memory management. In particular, we will talk more about the problem of method parameters.