C/C ++ memory allocation and Memory Allocation
I. prerequisites-program memory allocation:
The memory occupied by a C/C ++ compiled program is divided into the following parts:
1. stack: the stack zone is automatically allocated and released by the compiler, and stores function parameter values and local variable values. The operation method is similar to the stack in the data structure.
2. heap-generally assigned and released by the programmer. If the programmer does not release the heap, it may be recycled by the OS at the end of the program. Note that it is different from the heap in the data structure. The allocation method is similar to the linked list.
3. Global (static)-the storage of global variables and static variables is put in one area, and the initialized global variables and static variables are in one area, uninitialized global variables and uninitialized static variables are in another adjacent area. The program is released by the system.
4. Text Constant Area-constant strings are placed here. The program is released by the system.
5. Code Area
For example:
1 // main. cpp 2 int a = 0; // global initialization zone 3 char * p1; // global uninitialized Zone 4 main () 5 {6 int B; // stack 7 char s [] = "abc"; // stack 8 char * p2; // stack 9 char * p3 = "123456 "; // 123456 \ 0 is in the constant zone, and p3 is in the stack. 10 static int c = 0; // global (static) initialization zone 11 p1 = (char *) malloc (10); 12 p2 = (char *) malloc (20 ); // The allocated 10-byte and 20-byte areas are in the heap area. 13 strcpy (p1, "123456"); // 123456 \ 0 is placed in the constant area, and the compiler may optimize it to a place as directed by p3 "123456. 14}
Ii. Theoretical knowledge of heap and stack
2.1 Application Method
Stack: automatically allocated by the system. For example, declare a local variable int B in the function; the system automatically opens up space for B in the stack.
Heap (heap): the programmer must apply for it and specify the size. In c, the malloc function, such as p1 = (char *) malloc (10); such as p2 = (char *) malloc (10); but note that p1 and p2 are in the stack. Use the new operator in C ++.
2.2 system response after application
STACK: as long as the remaining space of the stack exceeds the applied space, the system will provide the program with memory. Otherwise, an exception will be reported, prompting stack overflow.
Heap: First, you should know that the operating system has a linked list that records idle memory addresses. When the system receives a program application, it will traverse the linked list, find the heap node with the first space greater than the requested space, delete the node from the idle node linked list, and allocate the space of the node to the program. In addition, for most systems, the size of the allocation will be recorded at the first address in the memory space, so that the delete statement in the code can correctly release the memory space. In addition, because the size of the heap node is not necessarily equal to the applied size, the system automatically places the excess part in the idle linked list.
2.3 Application size limit
STACK: in Windows, a stack is a data structure extended to a low address and a continuous memory area. The stack top address and the maximum stack capacity are pre-defined by the system. In WINDOWS, the stack size is 2 MB (OR 1 MB, in short, it is a constant determined during compilation. If the requested space exceeds the remaining space of the stack, overflow will be prompted. Therefore, the space available from the stack is small.
Heap: the heap is a data structure extended to the high address and a non-sequential memory area. This is because the system uses the linked list to store the idle memory address, which is naturally discontinuous, And the traversal direction of the linked list is from the low address to the high address. The heap size is limited by the valid virtual memory in the computer system. It can be seen that the space obtained by the heap is flexible and large.
2.4 comparison of application efficiency:
STACK: the stack is automatically allocated by the system, and the speed is fast. But programmers cannot control it.
Heap: Memory allocated by new. It is generally slow and prone to memory fragments. However, it is most convenient to use.
In addition, in WINDOWS, the best way is to use Virtual Alloc to allocate memory. Instead of heap or stack, the Virtual Alloc directly keeps a piece of memory in the address space of the process, although it is the most inconvenient to use. However, it is fast and flexible. VirtualAlloc is an API provided by Windows and is usually used to allocate large volumes of memory. For example, if you want to achieve communication between process A and process B by sharing the memory, you can use this function (this is also A common situation ).
Storage content in 2.5 heap and stack
STACK: when calling a function, the first entry to the stack is the address of the next instruction in the main function (the next executable statement in the function call statement), and then the parameters of the function, in most C compilers, parameters are written from right to left into the stack, followed by local changes in the function.
Quantity. Note that static variables are not included in the stack.
When the function call ends, the local variable first goes out of the stack, then the parameter, and the top pointer of the stack points to the address of the initial storage, that is, the next instruction in the main function, where the program continues to run.
Heap: Generally, the heap size is stored in one byte in the heap header. The specific content in the heap is arranged by the programmer.
2.6 comparison of access efficiency
Char s1 [] = "aaaaaaaaaaaaa ";
Char * s2 = "bbbbbbbbbbbbbbbbb ";
Aaaaaaaaaaa is assigned a value at the runtime;
Bbbbbbbbbbbbb is determined during compilation;
However, in future access, the array on the stack is faster than the string pointed to by the pointer (such as the heap.
For example:
1 #include <iostream> 2 void main() 3 { 4 char a=1; 5 char c[]="1234567890"; 6 char *p="1234567890"; 7 a = c[1]; 8 a = p[1]; 9 return;10 }
Corresponding assembly code
10: a = c [1];
004010678A4DF1movcl, byteptr [ebp-0Fh]
0040da-a884dfcmovbyteptr [ebp-4], cl
11: a = p [1];
00401_d8b55ecmovedx, dwordptr [ebp-14h]
004010708A4201moval, byteptr [edx + 1]
004010738845 FCmovbyteptr [ebp-4], al
The first method reads the elements in the string directly to the cl register, while the second method reads the pointer value to the edx.
Reading characters by edx is obviously slow.
2.7 summary:
The difference between stack and stack can be seen in the following metaphor:
Using Stacks is like eating at a restaurant, just ordering food (sending an application), paying for it, and eating (using it). If you are full, you can leave, without having to worry about the preparation work, such as cutting and washing dishes, as well as the cleaning and tail work such as washing dishes and flushing pots, his advantage is fast, but his degree of freedom is small.
Using heap is like making your favorite dishes. It is troublesome, but it suits your taste and has a high degree of freedom.
Iii. differentiate char * and char []
Char * defines a pointer to a string (note: the C language does not contain the built-in type or class type of the corresponding string), and char [] is used to define character arrays in C Language (note: character arrays are different from character strings. If the character array ends with '/0', it can be considered as a string ).
Char a [] is assigned a value at runtime, and the value is assigned from the static zone to the function stack. modifying it will not cause any problems. Char * a is determined during compilation. a points to the value in the static zone and is not assigned to the function stack. Therefore, an error occurs when you modify the pointer content.
Problem introduction:
An error. Similarly, char * c = "abc" and char c [] = "abc" are changed.
The program crashes, and the latter is completely correct.
Program Demonstration:
#include <iostream>using namespace std;main(){ char *c1 = "abc"; char c2[] = "abc"; char *c3 = ( char* )malloc(3); c3 = "abc"; printf("%d %d %s\n",&c1,c1,c1); printf("%d %d %s\n",&c2,c2,c2); printf("%d %d %s\n",&c3,c3,c3); getchar();}
Running result
2293628 4199056 abc
2293624 2293624 abc
2293620 4199056 abc
Self-summary:
Char * c1 = "abc"; in fact, a piece of memory is allocated in the text constant area to put "abc", and then an address is allocated to c1 on the stack and points to this address, then changing the constant "abc" will naturally crash.
However, char c2 [] = "abc", in fact, the memory allocated by abc is not the same as that of the upper user.
4199056
2293624 we can see that there are two parts. It is inferred that 4199056 is in the constant zone, and 2293624 is in the stack zone.
2293628
2293624
2293620 this output shows that the areas allocated by the three pointers are Stack zones, from high address to low address.
2293620 4199056 abc indicates that the compiler points c3 optimization to the "abc" of the constant zone"
Continue Thinking:
Code:
#include <iostream>using namespace std;main(){ char *c1 = "abc"; char c2[] = "abc"; char *c3 = ( char* )malloc(3); // *c3 = "abc" //error strcpy(c3,"abc"); c3[0] = 'g'; printf("%d %d %s\n",&c1,c1,c1); printf("%d %d %s\n",&c2,c2,c2); printf("%d %d %s\n",&c3,c3,c3); getchar();}
Output:
2293628 4199056 abc
2293624 2293624 abc
2293620 4012976 gbc
Write comments, and subsequent changes will crash.
It can be seen that strcpy (c3, "abc"); abc is allocated in another place and can be changed.
The C3 pointer itself is on the stack, but the pointing content is already on the stack.
4. Different memory allocation methods in Windows
(1) malloc
The C language memory allocation function is used to allocate general memory space. The memory allocated by this function is not automatically initialized. If you use C Programming, use this function. In Visual C ++, the malloc function calls the HeapAlloc function.
The memory allocated by malloc is released by the free function.
(2) new
In Visual C ++, HeapAlloc is called to implement memory allocation. If C ++ programming is used, it is recommended to use new to Allocate general memory. The system determines whether to initialize the object based on the call method.
Note: new is actually an operator rather than a function in C ++.
The memory allocated with new is released by delete/delete.
(3) VirtualAlloc
PVOID VirtualAlloc (PVOID pvAddress, SIZE_T dwSize, DWORD fdwAllocationType, DWORD fdwProtect)
VirtualAlloc is an API provided by Windows and is usually used to allocate large volumes of memory. For example, if you want to achieve communication between process A and process B by sharing the memory, you can use this function (this is also A common situation ). Do not use this function to allocate memory normally. An important feature of this function is that you can reserve the virtual memory space of the specified address and size. For example, if you want to allocate memory at 50 MB in the process address space, pass the parameter 50*1024*'1024 = 52428800 to pvAddress and pass the required memory size to dwSize. If the system has enough idle areas to meet the request, the system will reserve the area and return the base address of the reserved memory. Otherwise, NULL is returned.
The memory allocated using VirtualAlloc needs to be released using VirtualFree.
(4) HeapAlloc
HeapAlloc is an API provided by Windows. During process initialization, the system creates a 1 MB Heap in the address space of the process, which is called the Default Heap, you can change the value through the/HEAP connector switch. You can also create an additional heap through HeapCreate. The usage of the heap can manage the memory more effectively to avoid thread synchronization overhead and quickly release the memory. HeapAlloc is used to allocate a memory block from the stack. If the allocation is successful, the address of the memory block is returned. HeapAlloc internally determines the specific implementation based on the request size and heap size. For example, when a large memory space is required, the VirtualAlloc function is automatically called to allocate space. This function is usually used to allocate memory space of a general size. Some Windows APIs may require this function to allocate memory and pass it to API parameters. Note: When allocating large memory blocks (for example, 1 MB or more), it is best to avoid using heap functions. VirtualAlloc is recommended.
Use HeapFree to release memory allocated by HeapAlloc.