1. Significance of dynamic memory allocation
When we usually define a variable or an array, its size is a fixed value. Unable to be flexible, we can use dynamic memory allocation to solve the problem.
2. Dynamic memory function
2.1malloc
void* malloc (size_t size);
Where size is the number of bytes to be applied, and the type is size_t;
Pointer to the memory block allocated by the function when the return value is void * success. The type of this pointer is always void *, which can be converted to the required data pointer type. If the function fails to allocate the requested memory block, it returns a null pointer.
After we use the dynamic memory allocation function, the applied memory will be released. Here we use:
void free (void* ptr);
To free up the obtained memory.
Give an example of use.
#include<stdlib.h> #include<stdio.h> int main() { int *p = (int *)malloc(10 * sizeof(int)); int i = 0; for (i = 0; i < 10; i++) { p[i] = i; } for (i = 0; i < 10; i++) { printf("%d ", p[i]); } printf("\n"); free(p); return 0; }
2.2calloc
void* calloc(size_t num,size_t size);
Allocate a memory block for the num element array, each element is byte long, and initialize all its bits to zero. The valid result is to allocate (num*size) bytes of zero to initialize the memory block. If the size is zero, the return value depends on the specific library implementation (it may or may not be a null pointer), but the reference to the return pointer should not be dereferenced.
#include<stdlib.h> #include<stdio.h> int main() { int *p = (int *)calloc(10, sizeof(int)); if (p == NULL) { return 1; } return 0; }
By looking at the memory, we can see that the requested space is indeed initialized to 0.
2.3realloc
When we use dynamic memory application to obtain insufficient memory, we can use realloc to increase its space. Its prototype is
void* realloc (void* ptr, size_t size);
ptr is a pointer to a memory block previously allocated using malloc, calloc, or realloc. Alternatively, this can be a null pointer, in which case a new block will be allocated (as if malloc had been called).
Size is the new size of the memory block, in bytes. size_t is an unsigned integer type.
#include<stdlib.h> #include<stdio.h> int main() { int *p = (int *)malloc(10 * sizeof(int)); int i = 0; for (i = 0; i < 10; i++) { p[i] = i; } int *c = (int *)realloc(p, 20 * sizeof(int));//Expand capacity /*if (c != NULL) { p = c; } */ for (i = 10; i < 20; i++) { c[i] = i; } for (i = 0; i < 20; i++) { printf("%d ", c[i]); } printf("\n"); free(c); return 0; }
It should be noted here that when there is enough continuous space in the memory, the allocated backward continuous space returns the original pointer. When the continuous space is insufficient, a new memory will be found to copy the original data, and the new space can also be used.
3. Common dynamic memory errors
3.1 dereference of NULL pointer
If dynamic memory request 1 fails, null pointer will be returned, and dereference error will occur.
3.2 cross border access to dynamic development space
int main() { int *p=(int*)malloc(10* sizeof( int)); int i = 0; for (i = 0; i < 13; i++)//Space out of bounds access to dynamic memory allocation. { p[i] = i; } free(p); return 0; }
3.3 use free release for non dynamic memory
int main() { int p = 0; free(p);//Use free release for non dynamic memory return 0; }
3.4 use free to release a part of dynamic memory
void text() { int *p = (int *)malloc(10 * sizeof(int));//Release of some dynamic memory requests. p++; free(p); }
3.5 multiple releases of the same dynamic memory
void text() { int *p = (int *)malloc(10 * sizeof(int));//Multiple releases of dynamic memory. free(p); free(p); }
3.6 dynamic memory release
Although the program will be released automatically at the end of the program, it may cause serious memory waste in large projects.
4. Flexible array
Below is a flexible array.
struct student { int i; int a[];//It can also be written as a[0] };
4.1 characteristics and application 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 adapt to the expected size of the flexible array.
struct student { int j; int a[];//Flexible array }a; int main() { int i = 0; struct student *p = (struct student*)malloc(sizeof(a)+100 * sizeof(int));//This is equivalent to a[100] p->j = 100; for (i = 0; i<100; i++) { p->a[i] = i; } free(p); return 0; }
4.2 advantages of flexible array
Flexible arrays have the following two advantages for dynamic memory applications
1. Easy memory release
If our code is in a function for others, you make a secondary memory allocation in it and return the whole structure to the user. The user can release the structure by calling free, but the user does not know that the members in the structure also need free, so you can't expect the user to find it. Therefore, if we allocate the memory of the structure and the memory required by its members at one time and return a structure pointer to the user, the user can free all the memory once.
2. This is conducive to access speed
Continuous memory is beneficial to improve access speed and reduce memory fragmentation.