Table of contents
- 1. Why is there dynamic memory allocation
- 2. Introduction to dynamic memory functions
- 3. Common dynamic memory errors
-
- 1. Dereference operation on NULL
- 2. Cross-border access to the dynamically opened space
- 3. Release the non-dynamically opened space
- 4. Use the free function to release part of the dynamically opened space
- 5. Multiple releases of a dynamically opened space
- 6. Dynamic memory is allocated but forgot to release (resulting in memory leaks)
- Fourth, memory development
- Five, flexible array
- end
1. Why is there dynamic memory allocation
In the previous study, we learned 数据类型+变量名
to apply for a space.
int a = 100;
int arr[10] = {
0 };
The memory size of the space opened up in this way is fixed.
So how can the memory size of the application space be changed? ?
Then dynamic memory management is introduced here .
2. Introduction to dynamic memory functions
首先下面介绍函数的头文件都是 #include <stdlib.h>
The following about the perror function and the strerror function are mentioned in the introduction of the strerror function .
1. malloc function
void* malloc (size_t size);
The malloc function can apply for a space and pass back the first address of the applied space as the return value.
Notice:
1.1 The return value of the malloc function : if the malloc function is successfully applied, it will return the first address of the space , and if the application is not successful, it will return NULL
.
1.2 The use of malloc function : Since the person who designed the malloc function does not know which type of variable we apply for space to store , we will know which variable to store when we use it, so when using it, we must return the valuecastinto the type we need.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
//假设这里申请十个整形内存大小的空间
int* p = (int*)malloc(10 * sizeof(int));
//判断是否申请成功
if (p == NULL)
{
printf("malloc:%s\n",strerror(errno));
perror("malloc");//若申请失败则打印malloc失败的原因
//这里strerror函数与perror函数的作业相同
return 1;
}
//使用
for (int i = 0; i < 10; i++)
{
p[i] = i + 1;
}
for (int i = 0; i < 10; i++)
{
printf("%d ", p[i]);
}
//释放
//...
return 0;
}
2. calloc function
void* calloc (size_t num, size_t size);
The calloc function can apply for space like the malloc function, but the calloc function can initialize all the requested space to 0
.
Notice:
2.1 Parameters of the calloc function : two parameters are required, the first parameter is the requirednumber of elements, the second parameter is thememory size.
2.2 The return value of the calloc function : the same as the malloc function , the application returns the value of the spacefirst address, otherwise returns NULL
.
2.3 Use of the calloc function : Like the malloc function , the return value needs to becastinto the type you need.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int* p =(int*) calloc(10, sizeof(int));
if (p == NULL)
{
perror("calloc");
return 1;
}
//使用
for (int i = 0; i < 10; i++)
{
printf("%d ", p[i]);
}
//释放
//....
return 0;
}
3. realloc function
void* realloc (void* ptr, size_t size);
The realloc function can adjust the space requested by the malloc function and the calloc function .
Notice:
3.1 Parameters of the realloc function : two parameters are required, the first parameter isThe address of the memory space needs to be adjusted, the second parameter isAdjusted memory size.
3.2 The return value of the realloc function : the same as the malloc function and the calloc function , the adjustment successfully returns the value of the spacefirst address, otherwise returns NULL
.
3.3 Use of the realloc function : Like the malloc function and the calloc function , the return value needs to becastinto the type you need.
3.4 The realloc function can not only adjust the requested space, but when the first parameter of the realloc function NULL
is , it can directly apply for a space just like the malloc function.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int i = 0;
//这里开辟5个int类型内存的大小的空间
int* p = malloc(5 * sizeof(int));
if (p == NULL)
{
perror("malloc");
return 0;
}
//使用
for (i = 0; i < 5; i++)
{
p[i] = i + 1;
}
for (i = 0; i < 5; i++)
{
printf("%d ", p[i]);
}
printf("\n");
//这里将malloc函数开辟的5个int内存大小调整为10个
int* ptr = realloc(p, 10 * sizeof(int));
if (ptr == NULL)
{
perror("realloc");
return 1;
}
//这里若realloc函数返回的值不为NULL
p = ptr;
for (i = 5; i < 10; i++)
{
p[i] = i + 1;
}
for (i = 0; i < 10; i++)
{
printf("%d ", p[i]);
}
//释放
//...
return 0;
}
3.5 The principle of the realloc function
(1) When the continuous space after the parameter address is larger than the size of the space to be adjusted, the realloc function will directly adjust the space directly behind the incoming address.
(2) When the continuous space after the parameter address is smaller than the space to be adjusted, the realloc function will apply for another continuous space , and return the first address of this continuous space as the return value, and the original space will be released .
4. free function
void free (void* ptr);
The free function can release the space created by dynamic memory.
Notice:
4.1 If the parameters of the incoming functionnot dynamically typedout, causing undefined behavior to occur, which may crash the program or produce other unexpected results.
4.2 If the parameter passed into the function is NULL
, then the function does nothing.
3. Common dynamic memory errors
1. Dereference operation on NULL
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(4 * sizeof(int));
//如果这里p不进行判断,如果p为NULL
//那么这里就是对NULL进行解引用操作
*p = 4;
free(p);
p = NULL;
return 0;
}
2. Cross-border access to the dynamically opened space
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(5 * sizeof(int));
//判断
if (p == NULL)
{
perror("malloc");
return 0;
}
int i = 0;
//使用
for (i = 0; i <= 5; i++)
{
p[i] = i; //当i = 5的时候越界访问
}
//释放
free(p);
p = NULL;
return 0;
}
3. Release the non-dynamically opened space
int main()
{
int a = 10;
int* p = &a;
free(p);
return 0;
}
4. Use the free function to release part of the dynamically opened space
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(5 * sizeof(int));
//判断
if (p == NULL)
{
perror("malloc");
return 0;
}
p++;
//释放
free(p);
p = NULL;
return 0;
}
5. Multiple releases of a dynamically opened space
Notice: If the pointer is set to 0 after each release NULL
, then there will be no problem here, and the subsequent free functionNULL
will not perform any operations relative to the release .
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(5 * sizeof(int));
//判断
if (p == NULL)
{
perror("malloc");
return 0;
}
free(p);
//释放
free(p);
p = NULL;
return 0;
}
6. Dynamic memory is allocated but forgot to release (resulting in memory leaks)
void test()
{
int* p = (int*)malloc(sizeof(int));
if (p == NULL)
{
perror("malloc");
return 0;
}
*p = 100;
}
int main()
{
while (1)
{
test();
}
return 0;
}
Fourth, memory development
1. stack
The main function of the stack area is to store information such as temporary variables , function parameters , and function return addresses when the function is called .The stack area is used from the high address.
2. Heap
The heap area is mainly a space for storing dynamic memory development applications. Generally, it needs to be released after use. If you forget to release it, the space requested by dynamic memory development will be released by the operating system .The heap area is used from the lower addresses.
3. Data segment
The data segment is also called the data area and the static data area. It is used to store global variables and static data (variables modified by static), and is automatically recovered after the program ends.
4. Code snippet
The code segment is used to store binary code for executing instructions . It usually contains the program's instructions, constant values, and global variables.
Five, flexible array
1. Features of flexible arrays
1.1 The flexible array is in the structure, frontmustThere is at least one other type of structure member.
1.2 When the structure contains a flexible array, when sizeof()
calculating the size of the structure, it is not counted as a flexible array.
1.3 The structure containing flexible array members uses malloc ()
the function to dynamically allocate memory. When we open up a space, we must expect the size of the flexible array to facilitate the use of the flexible array.
2. The use of flexible arrays (code 1)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node
{
int a;
char c;
int arr[];
}Node; //这里重命名了,但未使用
int main()
{
//申请空间 结构体大小 + 10个整形大小
struct node* p = (struct node*)malloc(sizeof(struct node) + 10 * sizeof(int));
//这里相当于柔性数组申请了10 int类型大小的空间
if (p == NULL)
{
perror("malloc");
return 1;
}
//使用
p->a = 10;
p->c = 'v';
for (int i = 0; i < 10; i++)
{
p->arr[i] = i + 1;
}
for (int i = 0; i < 10; i++)
{
printf("%d ", p->arr[i]);
}
//释放
free(p);
p = NULL;
return 0;
}
3. Complete the function of flexible array without using flexible array (code 2)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node
{
int a;
char c;
int* pa;
}Node;
int main()
{
//申请空间 结构体大小 + 10个整形大小
struct node* p =(struct node*) malloc(sizeof(struct node));
//判断第一次malloc是否成功
if (p == NULL)
{
perror("malloc1");
return 1;
}
//这里申请十个int类型大小的空间,并将申请的空间赋给p->pa
p->pa = (int*)malloc(sizeof(int) * 10);
//判断第二次malloc是否成功
if (p->pa == NULL)
{
perror("malloc2");
return 1;
}
for (int i = 0; i < 10; i++)
{
p->pa[i] = i + 1;
}
for (int i = 0; i < 10; i++)
{
printf("%d ", p->pa[i]);
}
//释放
free(p->pa);
p->pa = NULL;
free(p);
p = NULL;
return 0;
}
4. Get the benefits of using flexible arrays by comparing Code 1 and Code 2
(1) The use of flexible arrays can facilitate the release of memory
incode oneWe only apply for space once and release space once . andcode twoIn the process, we apply for the space twice and release the space twice . When applying, we needFirstApply space to the structure,AgainApply for space for the pointers in the structure members, and when releasingFirstRelease the pointer application space in the structure member,AgainFree the space allocated for the structure. If the user does not know that the program first releases the space requested by the structure, then no one knows the location of the space requested by the pointer in the member of the structure and cannot be released.
(2) It can reduce memory fragmentation and speed up access (but not much).
end
If you have any suggestions and questions, or if there are any mistakes, I hope everyone can mention them.
I hope everyone can make progress with me in the future! !
If this article is useful to you, I hope you can give me a little like!