Dynamic memory management
Why is there dynamic memory allocation
What kind of memory development method have we mastered so far
//Create a variable int val = 20; //Local variables open up 4 bytes in stack space int g_val = 10; //The global variable opens up 4 bytes in the static area //Create an array char arr[10] = {0}; //The local area opens up 10 bytes of continuous space in the stack space char g_arr[5] = {0};//The global area opens up a continuous space of 5 bytes in the static area space
However, the above-mentioned way of opening up space has two characteristics:
- The size of the space is fixed.
- When declaring an array, you must specify the length of the array, and the memory it needs will be allocated at compile time.
But the demand for space is not just the above situation. Sometimes the size of the space we need can only be known when the program is running, and the way of opening up space during array compilation can not be satisfied. At this time, you can only try dynamic memory development.
c99 supports variable length arrays, but now many compilers do not support c99, even vs, so there is the concept of dynamic memory
Introduction to dynamic memory functions
malloc request space and free space
c language provides a function of dynamic memory development
void* malloc(size_t size);
This function requests a continuously available space from memory and returns a pointer to this space.
1. If the development is successful, a pointer to the developed space will be returned.
2. If the development fails, a NULL pointer will be returned. Therefore, the return value of malloc must be checked.
3. The type of the return value is void, so the malloc function does not know the type of open space, which is determined by the user when using it*
4. If the parameter size is 0, the behavior of malloc is not defined in the standard, which depends on the compiler.
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> int main() { //Request 10 shaping spaces from memory int* p = (int*)malloc(10 * sizeof(int)); if (p == NULL) { //Print out the failed information printf("%s",strerror(errno)); } else { //Normal use space int i = 0; for (i = 0; i < 10; i++) { *(p + i) = i;//Looking for element with index i } for (i = 0; i < 10; i++)//Then print out each element { printf("%d ", *(p + i)); } } return 0; }
Can we look at the failure of the development
We can use INT_MAX (he is the biggest), a super big number
Borrow and return free to free memory
The free function is used to free dynamic memory.
1. If the space pointed to by the parameter ptr is not dynamically opened up, the behavior of the free function is undefined.
2. If the parameter ptr is a NULL pointer, the function does nothing.
be careful
malloc and free are used in pairs. Who opens up and who releases
calloc request memory
Open up an array in memory and change the elements to zero
The function is to open up a space for num size elements, and initialize each byte of the space to 0.
The only difference between calloc and malloc is that calloc initializes each byte of the requested space to all zeros before returning the address
realloc resizes dynamic memory
Of course, we can apply for space, but will we encounter insufficient space, want to add some, and want to remove some when it is large
Precautions for using realloc
1. If there is enough memory space to append after the space pointed to by p, append directly and then return to p
2. If there is not enough memory space to add after the space pointed to by p, the realloc function will find a new memory area, open up a space to meet the needs, copy the data in the original memory back, release the old memory space, and finally return the newly opened memory space address
3. But there is also a big problem, that is, developing INT_MAX, use the new variable ptr to receive the return value of realloc
Of course, realloc can also directly open up space
Common dynamic memory errors
1. Dereference of NULL pointer
#include<stdio.h> #include<stdlib.h> int main() { int* p = (int*)malloc(40);//Without success, there will be big problems int i = 0; for (i = 0; i < 10; i++) { *(p + i) = i; } free(p); p = NULL; return 0; }
Therefore, in order to prevent the failure to open up dynamic memory, we need to make a judgment
2. Cross border visits to dynamic open spaces
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> int main() { int* p = (int*)malloc(5*sizeof(int)); if (p == NULL)//Here I do judge whether the development has been successful { printf("%s", strerror(errno)); } else { int i = 0; for (i = 0; i < 10; i++)//But I access 10 integer spaces here { *(p + i) = i; } } free(p); p = NULL; return 0; }
3. Use free to release non dynamic memory
int main() { int a = 0; int* p = &a; *p = 20; free(p); p = NULL; return 0; }
4. Use free to release part of a dynamic memory
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> int main() { int* p = (int*)malloc(40); if (p == NULL) { return 0;//If it is a null pointer, it will return directly and quit } int i = 0; for (i = 0; i < 10; i++) { *p++ = i;//This + + is where the bug is } //Recycle space free(p); p = NULL; return 0; }
As long as p is not the first address pointing to the requested space, it is wrong everywhere else
5. Release the same dynamic memory multiple times
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> int main() { int* p = (int*)malloc(40); if (p == NULL) { return 0; } //use //release free(p); //... free(p); return 0; }
6. Dynamic memory forgetting to release (memory leakage)
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> int main() { while (1) { malloc(100); } return 0; }
Several interview questions
Topic 1
void GetMemory(char* p) { p = (char*)malloc(100); } void Test(void) { char* str = NULL; GetMemory(str); strcpy(str,"hello world"); printf(str);//This is similar to printf("%s",str); It's the same } int main() { Test(); return 0; }
Ask what the result will be when you run the Test function
Correct modification
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<errno.h> void GetMemory(char* *p) { *p = (char*)malloc(100); } void Test(void) { char* str = NULL; GetMemory(&str); strcpy(str,"hello world"); printf(str);//This is similar to printf("%s",str); It's the same free(str);//Release after use str = NULL; } int main() { Test(); return 0; }
Topic 2
char* GetMemory(void) { char p[] = "hello world"; return p; } void Test(void) { char* str = NULL; str = GetMemory(); printf(str); } int main() { Test(); return 0; }
What will be the result of running the Test function
Output random value
Correct modification
Since p has been destroyed, we can let it not destroy it and prolong its life cycle with static
char* GetMemory(void) { static char p[] = "hello world"; return p; } void Test(void) { char* str = NULL; str = GetMemory(); printf(str); } int main() { Test(); return 0; }
Topic 3
void GetMemory(char **p, int num) { *p = (char *)malloc(num); } void Test(void) { char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); }
This question is basically the same as the first question, but this question only has the error of memory leakage
Correct modification
#include<stdio.h> #include<stdlib.h> void GetMemory(char** p, int num) { *p = (char*)malloc(num); } void Test(void) { char* str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); free(str);//Release after use to prevent memory leakage str = NULL; } int main() { Test(); return 0; }
Topic 4
void Test(void) { char* str = (char*)malloc(100); strcpy(str, "hello"); free(str); if (str != NULL) { strcpy(str, "world"); printf(str); } }
Print out the results with very big problems
Correct modification
#include<stdio.h> #include<string.h> #include<stdlib.h> void Test(void) { char* str = (char*)malloc(100); strcpy(str, "hello"); free(str);//What is examined here is that free does not make str NULL after it is released, so the following if judgment has no effect. If it makes it work, let str be NULL str = NULL; if (str != NULL) { strcpy(str, "world"); printf(str); } } int main() { Test(); return 0; }
The real purpose of this question is to let you print nothing
Memory development of C/C + + programs
Several areas of C/C + + program memory allocation:
- Stack: when executing a function, the storage units of local variables in the function can be created on the stack. These storage units are automatically released at the end of function execution. Stack memory allocation is built into the instruction set of the processor, which is very efficient, but the allocated memory capacity is limited. The stack area mainly stores the local variables, function parameters, return data, return address, etc. allocated for running the function.
- heap: it is generally allocated and released by the programmer. If the programmer does not release it, it may be recycled by the OS at the end of the program. The allocation method is similar to a linked list.
- The data segment (static area) stores global variables and static data. Released by the system at the end of the program.
- Code snippet: the binary code that holds the function body (class member function and global function).