In C language, when we use arrays, we often have such a problem: when the array is declared, the length of the array must be specified, and the memory it needs is allocated at compile time. Sometimes, the space we open up is too small to meet our needs, and sometimes it is too large, resulting in a serious waste of space. So can we open up one space if we need one and two spaces if we need two? At this time, you can only try dynamic memory development.
1, malloc function and free function
C language provides a function for dynamic development: malloc function. The header file is stdlib h.
void* malloc (size_t size);
This function can apply for a continuously available space in memory. If the development is successful, it will return the pointer of the developed space. Otherwise, it will return NULL. Therefore, when using malloc, you must check the return value of the function to avoid NULL pointer reference. Since malloc function does not know what type of space to open up, it is generally necessary to perform forced type conversion when using it.
The free function is used to release and recycle dynamic memory. The header file is stdlib h.
void free (void* ptr);
The free function can only release functions with dynamic memory. If the space not pointed to is not dynamically opened up, the results of the free function are undefined.
#include<stdio.h> #include<stdlib.h> int main(void) { int* a = (int*)malloc(sizeof(int));//Give a dynamic space free(a); a = NULL; return 0; }
The above example simply illustrates the use of malloc function. It should be noted that in general, the return value of malloc function must be checked. At the same time, after using the malloc function, it should be released in time. At the same time, the referenced pointer is assigned null. Otherwise, the above a will become a wild pointer, which will lead to illegal access when used again later.
2, calloc function
The function of calloc is to open up a space for num elements of size, and initialize each byte of the space to 0. The difference between calloc and malloc is that calloc initializes each byte of the requested space to all zeros before returning the address.
void* calloc (size_t num, size_t size);
#include<stdio.h> #include<stdlib.h> int main(void) { int* p = (int*)calloc(10, sizeof(int));//Open up space for p dynamics free(p); return 0; }
3, realloc function
Sometimes, after using malloc function, we find that the application space is still too small, and sometimes it is too large. If we want to modify it again, we can use realloc function at this time. The header file is stdlib h.
void* realloc (void* ptr, size_t size);
ptr is the memory address to be adjusted, and size is the new size after adjustment. The return value is the starting position of the adjusted memory.
The realloc function can be adjusted in the following ways:
1. If there is enough space behind the original space, it can be expanded directly.
2. Find another space that meets the requirements, copy the value of the original space, and return the new space address at the same time.
When using the return result of realloc function, you should also judge whether the return value is NULL.
IV. common memory errors
1. Dereference NULL pointer
#include<stdio.h> #include<stdlib.h> void test() { int* p = (int*)malloc(INT_MAX / 4); if (p != NULL) { *p = 20;//If the value of p is NULL, there will be a problem and it needs to be judged printf("%d", *p);//20 } else { printf("Empty!"); } free(p); } int main(void) { test(); return 0; }
2. Cross border access to dynamically opened space
void test() { int i = 0; int* p = (int*)malloc(10 * sizeof(int)); if (NULL == p) { exit(EXIT_FAILURE); } for (i = 0; i <= 10; i++) { *(p + i) = i;//Cross border access when i is 10 } free(p); } int main(void) { test(); return 0; }
The program will crash.
3. free the non dynamic space
void test() { int a = 10; int* p = &a; free(p); } int main(void) { test(); return 0; }
4. Release only part of the dynamic memory
void test() { int* p = (int*)malloc(100); p++; free(p);//p no longer points to the beginning of dynamic memory } int main(void) { test(); return 0; }
The results are the same as above.
5. Release the same memory multiple times.
void test() { int* p = (int*)malloc(100); free(p); free(p);//Repeated release } int main(void) { test(); return 0; }
The same result.
6. Forget to release, resulting in memory leakage.
void test() { int* p = (int*)malloc(100); if (NULL != p) { *p = 20; } } int main() { test(); while (1); }
Dynamic memory is developed on the heap. The memory in it needs to be released manually. If it is not released, it may be automatically recovered by the system at the end of the last program.
The variables we usually write are in the stack and data segments (storing global variables and static variables). These do not need to be released manually. They have their own scope, which will be destroyed automatically. The space created on the heap needs to be released manually.