Introduction to dynamic memory functions
- malloc
- free
- calloc
- realloc
Why is there dynamic memory allocation
int val = 20; Open up four bytes in stack space char arr[10] ={0}; Open up 10 bytes of continuous space on the stack space However, the above-mentioned way of opening up space has two characteristics: 1.The size of the space is fixed. 2.When declaring an array, you must specify the length of the array, and the memory it needs will be allocated at compile time. However, the demand for space is not limited to the above situations. Sometimes the size of space we need can be known when the program is running, The way to open up space during the compilation of arrays cannot be satisfied. At this time j You can only try dynamic memory development
Introduction to dynamic memory functions
malloc
malloc open space free 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. The user can decide the specific type of space when using it
4. If the parameter size is 0, the behavior of mallocd is standard and undefined, depending on the compiler
free
c language provides another function free, which is specially used for dynamic memory release and recovery. The function prototype is as follows
void free(void* ptr);
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
malloc and free are declared in the stdlib.h header file,
calloc
c language also provides a function called calloc, which is also used for d dynamic memory allocation,
void* calloc(size_t num,size_t size);
1. The function is to open up a space for num size elements and initialize each byte of the space to 0
2. The difference from malloc is that malloc initializes each byte of the requested space to all zeros before returning the address
realloc
Therefore, how to initialize the contents of the requested memory space? It is convenient to use the calloch function to complete the task
realloc
1. The appearance of realloc function makes dynamic memory management more flexible
2. Sometimes we find that the space applied for in the past is small, and sometimes we feel that the space applied for is too large, so we have a reasonable time memory,
We will adjust the memory size flexibly. The realloc function can adjust the dynamic development memory size. The functions are as follows
void* realloc(void* ptr,size_t size);
ptr is the memory address to be adjusted
New size after resizing
The return value is the adjusted memory starting position
This function will also move the data in the original memory to a new space on the basis of adjusting the size of the original memory space
There are two situations when realloc adjusts memory space
Case 1: there is enough space after the original space
Case 2: there is not enough space after the original space
malloc usage
int main() { //Request 10 shaping spaces from memory int* p = (int*)malloc(10 * sizeof(int)); if (p == NULL) { printf("%s\n", strerror(errno)); } else { //Normal use space int i = 0; for (i = 0; i < 10;i++) { *(p + i) = i; } for (i = 0; i < 10; i++) { printf("%d ", *(p+i)); } } When the dynamically requested space is no longer used, it should be returned to the operating system free(p); p = NULL; This means that the relationship is broken and the phone number is still there, So let the phone number go free,Let you forget the number return 0; }
calloc usage
int main() { //malloc(10*sizeof(int)); Here is the total size int* p = (int*)calloc(10, sizeof(int)); //Here is to calculate several elements, and then the size of each element //calloc initializes the element to 0, but malloc does not if (p == NULL) { printf("%s\n", strerror(errno));//Type out the error code and the corresponding information } else { int i = 0; for (i = 0; i < 10; i++) { printf("%d ", *(p + i)); } } //Free up space //The free function is used to release the dynamically opened space free(p); p = NULL; return 0; }
realloc
realloc Adjust the size of dynamic memory space int main() { int* p = (int*)malloc(20); if (p == NULL) { printf("%s\n", strerror(errno)); } else { int i = 0; for (i = 0; i < 5; i++) { *(p + i) = i; } } Is using malloc Open up 20 bytes of space Suppose that 20 bytes here can't meet our use I hope we can have 40 bytes of space You can use it here realloc To adjust the dynamic memory realloc Precautions for use: 1.If p If there is enough memory space to append after the space pointed to, append directly and return p 2.If p There is not enough memory space to append after the space pointed to realloc The function will find a new memory area again Open up a space to meet the needs, and copy back the data in the original memory to free up the old memory space,last Returns the address of the newly opened memory space 3.You have to receive it with a new variable realloc Return value of function int* ptr = realloc(p,INT_MAX); if (ptr != NULL) { p = ptr; int i = 0; for (i = 5; i < 10; i++) { *(p + i) = i; } for (i = 0; i < 10; i++) { printf("%d ", *(p + i)); } } //Free memory free(p); p = NULL; return 0; }
Common dynamic memory errors
The first error is dereference of NULL pointer
int main() { int *p = (int*)malloc(40); //In case malloc fails, p is assigned NULL //So be sure to judge if (p == NULL) { printf("%s\n", strerror(errno)); } else { int i = 0; for (i = 0; i < 10; i++) { *(p + i) = i; } } free(p); p = NULL; return 0; }
Second error
Out of bounds access to dynamic memory
int main() { int *p = (int*)malloc(5 * sizeof(int));//Here it opens up five integer elements if (p == NULL) { printf("%s\n", strerror(errno)); } else { int i = 0; for (i = 0; i < 10; i++)//10 elements are accessed here, so cross-border access { *(p + i) = i; } } free(p); p = NULL; return 0; }
The third error is the misuse of free. Free is in the heap
int main() { int a = 10; int* p = &a; *p = 20; //Use of non dynamic memory free release free(p); p = NULL; return 0; }
Fourth error
Use free to release part of dynamic memory
int main() { int* p = (int*)malloc(40); if (p == NULL) { return 0; } int i = 0; for (i = 0; i < 10; i++) { *p++ = i; } //Recycle space free(p);//p no longer points to the beginning of dynamic memory The mistake here is p What is released is the space behind, not the space at the beginning p = NULL; return 0; }
Fifth error
Multiple releases of the same dynamic memory
void test() { int *p = (int *)malloc(100); free(p); free(p);//Repeated release }
The sixth error, dynamic development, memory forgetting to release (memory leak)
int main() { while (1) { malloc(1);//Free is not used to free memory } return 0; } Forgetting to release the dynamically opened space that is no longer used will cause memory leakage. Remember to release the dynamically opened space And must be released correctly
Several classic written questions
What will be the result of running the Test function
void GetMemory(char* p) { p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str, "hello world"); Here, the program will crash because the memory access fails, because str It doesn't point to effective space, Failure reason: 1.The program running the code will crash 2.There is a memory leak in the program str Pass values to p p yes GetMemory The formal parameters of a function can only be valid inside the function, etc GetMemory After the function returns, the dynamic memory has not been released, And can not be found, so it will cause memory leakage printf(str); } int main() { Test(); return 0; }
Improve the above code into the correct code
Improvement method 1 void GetMemory(char** p) { *p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(&str); strcpy(str, "hello world"); printf(str); } int main() { Test(); return 0; } Improvement method II char* GetMemory(char* p) { p = (char *)malloc(100); return p; } void Test(void) { char *str = NULL; str = GetMemory(str); strcpy(str, "hello world"); printf(str); } int main() { Test(); return 0; }
What will be output when the test function is executed
Structure is random value
char* GetMemory(void) { char p[] = "hello world"; //Here is a local variable, which is only valid inside the function. Its life cycle is to enter its scope, start its life cycle and leave its scope, //At the end of the life cycle, when you go out, you do return the address, but this space is returned to the operating system, and the values in this space are next //What is random return p; } void Test(void) { char* str = NULL; str = GetMemory(); printf(str); } int main() { Test(); return 0; }
Interview simulation questions return to stack space
int* test() { //static int a = 10; Static zone int a = 10;//Stack area //Just add a static in front of the stack area //Because static modifies local variables, the life cycle of local variables becomes longer. a is not destroyed except for the scope return &a; } int main() { int* p = test(); *p = 20; return 0; }
int* test() { int * ptr = malloc(100);//Only free can recycle the heap space in the heap area, so it is also possible here return ptr; } int main() { int* p = test(); return 0; }
What will be the result of running the Test function
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); str = NULL; //The print result here is hello /* Forget to release the dynamically opened memory, resulting in memory leakage. Use free to release it */ } int main() { Test(); return 0; }
void Test(void) { char *str = (char*)malloc(100); strcpy(str, "hello"); free(str); //After free releases the space pointed to by str, it will not set str to null, so you should add str = null and set free to null after free release if (str != NULL) { strcpy(str, "world"); //Illegal access to memory. You have released it, but you still want to access it printf(str); } } int main() { Test(); return 0; }
Several areas of memory allocation in c/c + + programs
1. Stack area: when the function is executed, the storage units of local variables in the function can be created on the stack. When the function is executed, these storage units can be created
The storage unit is automatically released, and the stack memory allocation operation is built into the instruction set of the processor, which is very efficient, but the allocated memory capacity is
The stack area mainly stores the local variables, function parameters, return data, return address, etc. allocated by the running function
2. Heap area: it is generally allocated and released by the programmer. If the programmer does not release it, the OS may be recycled at the end of the program. The allocation method is similar to the linked list
3. The data segment (static area) stores global variables and static data, which are released by the system after the program is completed
4. Code segment: the binary d code that stores the function body (class member function and global function)
In fact, ordinary local variables allocate k space in the stack area. The characteristic of the stack area is that the variables created above are destroyed when they are out of scope
However, the variables modified by static are stored in the data segment (static area). The data segment is characterized by the variables created on it, which are not destroyed until the end of the program
So the life cycle becomes longer
Flexible array
In C99, the last element in the structure is allowed to be an array of unknown size, which is called a [flexible array] member
Both methods are OK. If the compiler of the first method cannot compile, use the second method
The first method(1)If the compiler doesn't work, which of the following is used struct S { int n; int arr[]; //The last element in the structure is of unknown size Unknown size-Flexible array member -The size of the array can be adjusted }; (2) struct S { int n; int arr[0]; //The last element in the structure is of unknown size Unknown size-Flexible array member -The size of the array can be adjusted
Specific use of flexible arrays
struct S { int n; int arr[0];//Unknown size - flexible array members - the size of the array can be adjusted }; int main() { //Here is the space creation of flexible array struct S* ps = (struct S*)malloc(sizeof(struct S) + 5*sizeof(int)); ps->n = 100; //100 int i = 0; for (i = 0; i < 5; i++) { ps->arr[i] = i; // 0 1 2 3 4 } struct S* ptr = realloc(ps, 44);//Adjust the flexible array to become more points if (ptr != NULL) { ps = ptr; } for (i = 5; i < 10; i++) { ps->arr[i] = i; } for (i = 0; i < 10; i++)//Print here { printf("%d ", ps->arr[i]); } //Free up space free(ps); ps = NULL; return 0; }
Other methods
struct S { int n; int* arr; }; int main() { struct S* ps = (struct S*)malloc(sizeof(struct S)); ps->arr = malloc(5 * sizeof(int)); int i = 0; for (i = 0; i < 5; i++) { ps->arr[i] = i; } for (i = 0; i < 5; i++) { printf("%d ", ps->arr[i]); } //Resize int * ptr = realloc(ps->arr,10*(sizeof(int))); if (ptr != NULL) { ps->arr = ptr; } for (i = 5; i < 10; i++) { ps->arr[i] = i; } for (i = 0; i < 10; i++) { printf("%d ", ps->arr[i]); } //Free memory free(ps->arr); ps->arr = NULL; free(ps); ps = NULL; return 0; }
After two convenient comparisons, flexible arrays are better. malloc free uses less and has less error probability
The second method has a high error rate. The more malloc is used, the more memory fragments are used, and the memory utilization is low
Characteristics of flexible array
- A flexible array member in a structure must be preceded by at least one other member
- The size of this structure returned by. sizeof does not include the memory of the flexible array
- The structure containing flexible array members uses malloc() function to dynamically allocate memory, and the allocated memory should be larger than the size of the structure,
To accommodate the expected size of the flexible array
Advantages of flexible arrays
1. It is convenient to release the memory. You can release all the memory by making a free
2. This is conducive to access speed
Finally, a great God and its motto are introduced
Chen Hao