. NET memory base (through memory experience type, pass-through, and boxing unboxing)

Source: Internet
Author: User

This essay is inspired by the inter-connection of the CLR Via C # (third edition), chapter fourth 4.4 runtime

One, several areas of memory allocation

1. Thread stacks

A pointer (or reference) to a local variable's value type and a reference type in a local variable is assigned to that zone (a portion of the reference type's memory is assigned to the zone).

The area is controlled by the system and is not controlled by the garbage collector. When the method executes, the local variable is automatically freed (the reference type only releases the pointer, not the data pointed to by the pointer ).

The execution of the stack is highly efficient, but the capacity is limited.

2.GC Heap ( recycle heap )

Used to allocate small objects (reference types), and if the instance size of the reference type is less than 85000 bytes, it is assigned to that zone.

3.LOH (Large Object Heap)

Large Objects (reference types) that exceed 85000 bytes are assigned to the region.

The difference between the Loh and GC heap is that when there is memory allocation or recycling, the garbage collector may compress the GC heap , and the Loh is not compressed, but is recycled when it is garbage collected.

Second, stack frames (stack frame)

The stack frame is the data structure that implements the function call , logically, the stack frame is a function execution environment (context), including: function parameter, return address and function local variable.

Note: the "return address" above is not the return value of the function, but rather the location of the code that the CPU next executes after the function call is completed.

See also: Wikipedia call stack

Three, shallow copy and deep copy (clone, or clone )

Shallow copy and deep copy are two ways of memory copy, usually in the process of transmitting the memory copy and is a shallow copy, such as the following code, two parameters is two shallow copy.

        public void Test1 ()        {            string name = "Test1";            int size = 1;            TEST2 (name, size);//two light copy        } public        void Test2 (string pName, int pSize)        {        }

The memory results before and after the shallow copy are as follows:

A shallow copy is a value type (for example: int), and the copy is a specific value in the stack.

Shallow copy for a reference type (for example: string), copy the reference in the stack, the address in the managed heap to which the new reference is pointing, or the original address.

The difference between a deep copy and a shallow copy is the processing of data (that is, objects) in the heap :

A shallow copy copies only the references in the stack, does not copy the objects in the heap, and the new references point to the original objects.

A deep copy copies a reference in the stack and creates a new object in the heap, and the property value of the new object "may" originate from the original object (because, implementing a deep copy in C # requires you to write additional code yourself.

That is to implement the ICloneable interface, the result of a deep copy is indeterminate. However, we recommend that you avoid using the interface as much as possible, and the new reference address points to the new object. Therefore, the deep copy is only for reference types,

There is not much meaning for value types.

Four, Demo

If the top three is a cushion, then the demo is the text.

The following classes have been defined in advance:

    public class Data     {public        string Name;        public int Size;    }

Suppose the code is about to call the Test1 function:

        public void Test1 ()        {            string name = "Test1";            int size = 1;            Data data = new data () {Name = "test1", Size = 1};            TEST2 (name, size, data);            Object obj = size;            int temp = (int) obj;        }        public void Test2 (string pName, int pSize, Data pData)        {            pName = "Test2";            PSize = 2;            Pdata.name = "Test2";            Pdata.size = 2;                        PData = new Data () {Name = "test3", Size = 3};                    }

The situation in this line stacks and managed heap is as shown (Figure 1):

1 . Start calling the Test1 function, then press a stack frame into the stack.

The stack frame contains 3 pieces of data:

1) function parameters, of course Test1 function has no parameters.

2) return address, in the Test1 function, take the current code environment as an example the address does not have any practical meaning.

3) function local variables, at which time all local variables in the TEST1 function are pressed into the stack. The following five local variables are pressed into the stack:

String name, int32 size, data data, Object obj, Int32 temp. (Of course, there are six local variables, and the sixth one is generated automatically by the compiler and explained at the end of the essay.) )

After pressing into a stack frame, the memory results are as shown (Figure 2):

2, next executes the code of the TEST1 function, assigns a value to the name, assigns a value to the size, assigns a value to the data. The memory results will be as shown (Figure 3):

The Red Line in the and compiler-generated variables will be explained at the end of the essay.

3 . Next, the Test2 function is called, and a stack frame is pressed into the stack.

The stack frame contains 3 pieces of data:

1) function parameters, the TEST2 function has three parameters, and three parameters are shallow copies.

2) return address, which is the location of the next line (or next instruction) that calls the location of the TEST2 function code, namely:

obj = size; Object obj has been completed when calling the Test1 function into the stack frame; The operation

After the function call is complete, the above code is executed.

3) Function Local variables, the compiler will automatically generate a variable (at the end of the essay, will explain)

Therefore, the memory results are as shown in this case (Figure 4):

Two orange lines are the result of a shallow copy of the parameter.

4 . After executing the function body of the TEST2 function and not returning the TEST1 function, the memory result is as shown (Figure 5):

Red Line will be explained at the end of the essay.

Yellow Line Note that string is a special reference type that behaves as if it were a value type, but is essentially a reference type. Because of the immutability of string, each assignment to a string

Will produce a new object (if the new object does not exist), causing the yellow line to appear.

Light Green Line I think this line should have no problem.

5, complete the call of the TEST2 function, the code will return to the TEST2 function stack frame return address shown in the position, in this process the TEST2 function stack frame will be ejected, the results as shown (Figure 6):

Objects that are not being used in the managed heap are automatically reclaimed by the GC, and the time to be reclaimed is indeterminate.

6, by 3 can be known, the next will be executed obj = size; The operation- boxing , literally can be understood: The value type is loaded into the box of the reference type.

The approximate operation process is as follows:

1) First, create a new object in the heap. (The performance of the boxing operation is reduced due to this operation)

2) Copy the value of size to the object.

3) Finally point the reference to obj to the newly created object.

The final result is as shown (Figure 7):

7, the last operation-- unpacking .

Boxing is the case where the value type is loaded into a reference type box, in which object creation and memory replication occur.

Unpacking, however, is not as complicated as it is, and there is no such thing as a "tear-down" process, except that the value type in the object is read (the most time-consuming operation should be to look for the memory address of the value type), and its performance is much better than boxing.

The end result is as shown (Figure 8):

Five, syntax sugar--object initializer

The following two code fragments are fully equivalent:

            Data temp = new data (); The compiler automatically generates variable names that are not necessarily called temp            temp. Name = "Test1";            Temp. Size = 1;                        data = temp;

The second way of writing, can be seen as a shorthand, the compiler at the time of compilation will be the second type of code to convert, into the first form of writing. So the object initializer, the new syntax feature of c#3.0,

is completely a syntactic sugar, the CLR does not play any role.

When you see this, think about the Red line above .

. NET memory base (through memory experience type, pass-through, and boxing unboxing)

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.