. NET Six musketeers: Stacks, heaps, value types, reference types, boxing and unpacking
One. " Heap "," stack "zone
I believe you are too familiar with these two words, even rice is what? I don't know... What is "heap" and "stack"? Oh, this one knows ...
Before I also wrote a stack of articles, but not deep in writing, the analysis is not comprehensive, so today also refer to some of Daniel's information.
I. Preliminary knowledge-memory allocation of the program
The memory used by a program compiled by C + + is divided into the following sections
1. Stack (stack)-Automatically allocated by the compiler to release, store the function parameter value, local variable value and so on. Its
Operations are similar to stacks in data structures. A stack is an array of memory that is a LIFO (last-in first-out, LIFO) data structure.
2, heap area (heap)-Generally by the programmer assigned to release, if the programmer does not release, the end of the program may be the OS back
Inbox Note that it is different from the heap in the data structure. a heap is an area of memory in which large chunks of memory can be allocated to store data of a certain type.
Unlike stacks, the memory in the heap can be stored and removed in any order.
Although the program can save data in the heap, it is not possible to delete them as shown. The CLR's automatic GC (garbage Collector, garbage collector) again determines the program's
3, Global Zone (Static)-, the storage of global variables and static variables is placed in a block, initialized
Global variables and static variables in an area, uninitialized global variables and uninitialized static variables in adjacent
An area. -released by the system after the program is finished.
4, literal constant area-the constant string is put here. Released by the system after the program is finished
5. Program code area-binary code that holds the function body.
Ii. Examples of procedures
It was written by a predecessor, very detailed
Main.cpp
int a = 0; Global initialization Zone
Char *p1; Global uninitialized Zone
Main ()
{
int b; Stack
Char s[] = "ABC"; Stack
Char *p2; Stack
Char *p3 = "123456"; 123456/0 in the constant area, p3 on the stack.
static int c = 0; global (static) initialization zone
P1 = (char *) malloc (10);
P2 = (char *) malloc (20);
Areas that are allocated 10 and 20 bytes are in the heap area.
strcpy (P1, "123456"); 123456/0 in the constant area, the compiler may associate it with the "123456" that P3 points to
Optimized into one place.
}
third, heap and stack of theoretical knowledge
3.1 How to apply
Stack
Automatically assigned by the system. For example, declare a local variable int b in the function; The system automatically opens up empty for B in the stack.
Room
Heap
Requires the programmer to apply himself and indicate the size of the malloc function in C
such as P1 = (char *) malloc (10);
Using the new operator in C + +
such as P2 = new CHAR[10];
But note that P1, p2 itself is in the stack.
3.2
Response of the system after application
Stack: As long as the remaining space of the stack is larger than the requested space, the system will provide memory for the program, otherwise it will report the exception prompt stack Overflow
Out
Heap: First you should know that the operating system has a list of idle memory addresses, when the system receives the application of the program,
The linked list is traversed, looking for the first heap node that is larger than the requested space, and then linking the node from the Idle node list.
and allocates the space of that node to the program, and, for most systems, in this memory space
The size of this allocation is recorded at the first address so that the DELETE statement in the code can properly free up the memory space.
In addition, because the size of the found heap node does not necessarily exactly equal the size of the request, the system will automatically
Into the list of idle links.
3.3 Application Size Limits
Stack: Under Windows, the stack is the data structure to the low address extension, which is a contiguous area of memory. The meaning of this sentence
Think is the top of the stack address and the maximum capacity is the system pre-defined, under Windows, the size of the stack is 2M (there are
1M, which is a constant at compile time), if the requested space exceeds the stack's remaining space, the
Hint overflow. Therefore, the space available from the stack is small.
Heap: A heap is a data structure that extends to a high address, and is a discontinuous area of memory. This is because the system is stored with a linked list
The free memory address is, naturally, discontinuous, while the traversal direction of the list is addressed by the low address to the high address. The size of the heap
Limited by the virtual memory available in the computer system. Thus, the space of the heap is more flexible and relatively large.
3.4 Comparison of application efficiency:
The stack is automatically assigned by the system and is faster. But programmers can't control it.
Heap is the memory allocated by new, the general speed is relatively slow, and prone to memory fragmentation, but the most convenient to use.
In addition, under Windows, the best way is to allocate memory with VirtualAlloc, he is not in the heap, nor is the stack
Preserves a chunk of memory directly in the address space of the process, although it is most inconvenient to use. But the speed is fast, also the most flexible.
3.5 Storage contents in stacks and stacks
Stack: When a function is called, the first stack is the next instruction in the main function (the next bar of the function call statement can be
The address of the execution statement, and then the parameters of the function, in most C compilers, the arguments are left-to-right into the stack
, and then a local variable in the function. Note that static variables are not in the stack.
When the function call is finished, the local variable is first out of the stack, then the parameter, and the last stack pointer points to the first saved
The next instruction in the main function, and the program continues to run from that point.
Heap: The size of a heap is typically stored in a heap at the head of a pile. The concrete contents of the heap are arranged by the programmer.
3.6 Comparison of Access efficiency
Char s1[] = "AAAAAAAAAAAAAAA";
Char *s2 = "BBBBBBBBBBBBBBBBB";
AAAAAAAAAAA is assigned at run time;
And BBBBBBBBBBB is determined at compile time;
However, in subsequent accesses, the array on the stack is faster than the string that the pointer points to (for example, a heap).
Like what:
#include
void Main ()
{
char a = 1;
Char c[] = "1234567890";
Char *p = "1234567890";
A = c[1];
A = p[1];
Return
}
The corresponding assembly code
10:a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0fh]
0040106A 4D FC mov byte ptr [ebp-4],cl
11:a = p[1];
0040106D 8B-EC mov edx,dword ptr [ebp-14h]
00401070 8A mov al,byte ptr [edx+1]
00401073 FC mov byte ptr [ebp-4],al
The first reads the elements in the string directly into the register CL, and the second one reads the pointer value to
In edx, it is obviously slower to read the characters according to EdX.
Four. To understand stacks and heaps, let's use the following code to understand what's going on behind the scenes.
1 Public voidMethod1 ()2 {3 4 //Line 15 intI=4;6 7 8 //Line 29 inty=2;Ten One A //Line 3 -Class1 CLS1 =NewClass1 (); -}
The code is only three lines, and now we can do it one line at a time to see how the inside is executed.
- Line 1: When this row is executed, the compiler allocates a small chunk of memory on the stack. Stack will be in charge of tracking your application for running memory needs
- Line 2: The second step will now be performed. Just like the name of the stack, it overlays a small chunk of memory allocation here at the top of the memory allocation that was just the first step. You can think of a stack as a room or box that is stacked up. In the stack, the allocation and release of data is done through LIFO (last in First out), which is the advanced logic rule. In other words, the data item that is first entered in the stack is likely to end up in the stack.
- Line 3: in the third row, we created an object. When this line is executed,. NET creates a pointer in the stack, and the actual object is stored in a memory area called the heap. The heap does not monitor running memory, it is just a bunch of objects that can be accessed at any time. Unlike stacks, the heap is used for dynamic memory allocation.
- Another important point to note here is that the reference pointer of the object is allocated on the stack. For example: statement statement Class1 CLS1; Instead of allocating memory for an instance of Class1, it simply creates a reference pointer on the stack for the variable CLS1 (and assigns its default position to null). Only when it encounters the new keyword does it allocate memory on the heap for the object.
- when you leave this Method1 method (the Fun): Now the execution control statement begins to leave the method body, and all the memory space allocated for the variable on the stack is cleared. In other words, all variables related to type int in the example above will be stacked one by one from the stack in the form of "LIFO" LIFO.
- It is important to note that at this point it does not release the blocks of memory in the heap, and the blocks of memory in the heap will be cleaned up by the garbage collector.
Now many of our developer friends must be curious about why there are two different types of storage? Why can't we allocate all the memory blocks to only one type of storage?
If you watch carefully enough, the primitive data types are not complex, they just save values like ' int i = 0
. Object data types are complex and they reference other objects or other primitive data types. In other words, they hold references to multiple other values and these values must be stored in memory one by one. The object type requires dynamic memory and the primitive type requires static memory. If the requirement is dynamic memory, then it allocates memory on the heap, instead, it is allocated on the stack. The stack is accessed faster than the heap.
Finally give everyone a heap and the image of the stack metaphor:
Using stacks like we eat in a restaurant, just order (apply), pay, and eat (use), eat full
Go, do not bother to cut vegetables, wash vegetables and other preparation work and washing dishes, brush pots and other finishing work, his advantage is fast, but since
Small by degrees.
Using the heap is like making your own favorite dishes, more troublesome, but more in line with their own tastes, and free
The high degree.
Two. Value types and reference types
The CLR supports two types, reference types, and value types. The difference between the two types is that they are in the. NET class hierarchy are different, then. The way that net allocates memory for it is also different.
Cough cough! To put it bluntly: the value type is cash, to use directly, the reference type is the Passbook, you have to go to the bank first to take cash.
Declaring a value-type variable, the compiler allocates a space on the stack that corresponds to the value-type variable, where the value of the variable is stored in space. An instance of a reference type is allocated on the heap, and a new instance of the reference type is created, and the resulting variable value corresponds to the memory allocation address of the instance, just like your bank account.
All value types in C # are implicitly derived from System.ValueType:
- struct: struct (directly derived from System.ValueType);
- Numeric type:
- Integer: sbyte (alias of System.SByte), short (system.int16), int (System.Int32), long (System.Int64), Byte (System.Byte), ushort (system.uint16), uint (System.UInt32), ULONG (System.UInt64), char (System.Char);
- Float type: float (system.single), double (system.double);
- High-precision decimal type for financial calculations: decimal (System.Decimal).
- BOOL Type: bool (alias of System.Boolean);
- User-defined struct (derived from System.ValueType).
- Enum: Enum (derived from System.Enum);
- Nullable type (derived from system.nullable<t> generic struct, T? is actually an alias of system.nullable<t>).
Value type, the value type instance is typically assigned on the thread's stack (stack) and does not contain any pointers to the instance data, because the variable itself contains its instance data
C # has some of the following reference types:
- Array (derived from System.Array)
- The following types are defined by the user:
- Classes: Class (derived from System.Object);
- Interface: Interface (interface is not a "thing", so there is no question of where to derive it.) Anders in the C # programming Language, the interface simply represents a convention [contract]);
- Delegate: Delegate (derived from System.Delegate).
- Object (alias of System.Object);
- String: String (alias of System.String).
Can be seen:
- The reference type and the value type are the same, the struct can also implement the interface;
- A reference type can derive a new type, while a value type cannot;
- A reference type can contain a null value, and a value type cannot (a nullable type function allows NULL to be assigned to a value type);
- The assignment of a reference type variable copies only references to the object, not the object itself. When you assign a value type variable to another value-type variable, the contained value is copied
Then deep analysis on the memory, I do not understand so I do not write!
Three. Crating and unpacking
Box: Convert a value type object to a reference type object;
Unboxing (unbox): Convert a reference type object to a value type object.
C # Boxing and unpacking principles:
Packing:
int age = 24;
Object refage= age;
As you can see, the first statement creates a variable age and places the value in the managed stack;
The second statement assigns the value of age to the reference type. It places the value 24 in the managed heap.
This value type is packaged as a reference type of procedure, called boxing.
Unpacking:
Conversely, the process of converting a reference type to a value type is called unpacking. Unpacking will cast the object to its original type. Unboxing the previous object.
int newage = (int) refage;
String newage = (string) refage;
The value of the unboxing must have the same type as the variable to which it is to be converted.
The following is the code that we often write, so how does boxing and unboxing change in this process?
int n = 2;
Object obj = (object) n;//boxing, converting a numeric type int to a reference type Object object.
int m = (int) obj;//unboxing, converts object of reference type to int type.
We can see that C # code is compiled into the intermediate language IL, and it is clear that the process of boxing and unpacking:
In the actual coding process, which is the boxing and unpacking it?
1, reference types are not boxed and unboxing, boxing, unpacking must be: value type → reference type or reference type → value type.
Person P=new Student ();//This is called implicit type conversion, not called boxing.
Student stu= (Student) p;//This is called display type conversion, not called unboxing.
2. When overloading a method, it is not called unpacking or boxing if it has an overload of that type. int n=10; Console.WriteLine (n);//No boxing occurred because of method overloading. 3, the interface and the value type between the packing and the unpacking. int n = 2;
IComparable C = n;
int m = (int) c;
Console.WriteLine (M.tostring ());
To write an efficient, high-performance software, be aware of the impact of boxing and unpacking on your application. Personal advice to use less!
. NET Six musketeers: Stacks, heaps, value types, reference types, boxing and unpacking