Article directory
Preface
The title of the article is dynamic memory management. So what is dynamic memory management? Why is there dynamic memory management?
Looking back at the knowledge we have learned before, the methods we have mastered to open up memory are as follows:
char ch = 'a';
int val = 10;
float f_val = 12.8f;
int arr[20] = {
0 };
//....
The above method of opening up memory has several disadvantages:
- The size of the opened space is fixed
- When declaring an array, the length of the array must be specified. Once the size of the array space is determined, it cannot be adjusted.
But the demand for space is not just the above situation. Sometimes the amount of space we need can only be known when the program is running, so the method of allocating space for the array at compile time is not satisfactory.
C language introduces dynamic memory allocation, which allows programmers to apply for and release space by themselves, which is more flexible.
1.malloc
The function of this function is: apply for a block of memory continuous memory space, and thenreturnA pointer to the starting address of the spacepointer。
- If space
开辟成功
, returns a pointer to the starting address of the space. - If space
开辟失败
, a NULL pointer is returned. Therefore, the return value of the function needs to be checked - The opened space will not be initialized。
- The type of the return value is void*, so the function does not know the type of space to be opened, and the user who needs the space decides by himself.
- When the function's argument is 0, the return value is undefined and depends on the compiler.
- Header file stdlib.h
Use the malloc function to apply for 40 bytes of space
When the parameter of the function is 0, it is a random value in vs2019
Since the space is a program If someone applied for it, then who would be released in the end?
- The programmer releases it himself.
- The program ends and the operating system recycles
Here’s how to release
2.free
C language provides another function free, which is specially used to release and recycle dynamic memory. The function prototype is as follows:
- This function is used to release the space requested by malloc, calloc, and realloc.
- If the parameter ptr points toSpace is not opened dynamically, then the behavior of the free function is undefined.
- If the parameter ptr is a NULL pointer, the function does nothing.
- This function will not change the value of the pointer ptr, so in order to avoid the appearance of wild pointers, it must be set to NULL in time.
3.calloc
The function of this function is similar to malloc, the difference is:
- This function has two parameters, one is the number of elements, and the other is the size of each element.
- This function will initialize the requested space to all 0s.
4.realloc
The emergence of realloc function makes dynamic memory management more flexible.
Sometimes we find that the space we applied for in the past was too small, and sometimes we feel that the space we applied for is too large. In order to use the memory reasonably, we must make some adjustments to the memory size. Flexible adjustment. Then the realloc function can adjust the dynamically allocated memory size.
- ptr is the memory address to be adjusted
- size new size after adjustment
- The return value is the starting position of the memory after adjustment.
- This function adjusts the size of the original memory space and also
将原来内存中的数据移动到新的空间
. - There are two situations when realloc adjusts the memory space:
- Situation 1: There is enough space behind the original space
- Situation 2: There is not enough space after the original space
- Case 1
When it is case 1, if you want to expand the memory, just add space directly after the original memory.The data in the original space does not change。- Case 2
When it is case 2 and there is not enough space after the original space, the expansion method is: find another suitable space on the heap space Use large and small continuous spaces. In this way, the function returns a new memory address.
Since this function has two special cases, we should pay more attention when using it:
Is there any problem with the following code?
int main()
{
//1. 先申请一部分空间
int* p = (int*)malloc(20);
if (NULL == p)
{
perror("malloc");
return 1;
}
//2.扩容空间
p = (int*)realloc(p, 40);
if (NULL == p)
{
perror("realloc");
return 1;
}
//3.使用
//.......
free(p);
p = NULL;
return 0;
}
If realloc fails to open up space, then it will return a null pointer, and p is a null pointer.
Good guy, the expansion was not successful for me, and my previous data is gone. That’s great!
Therefore, when receiving the return value of realloc, we should use a temporary variable to receive it, determine whether the temporary variable is a null pointer, and then operate on p.
Therefore, it should be written like this:
#include<stdlib.h>
int main()
{
//1. 先申请一部分空间
int* p = (int*)malloc(20);
if (NULL == p)
{
perror("malloc");
return 1;
}
//2.扩容空间
int* tmp = NULL;
tmp = (int*)realloc(p, 40);
//先判断realloc的返回值
if (tmp != NULL)
{
p = tmp;
tmp = NULL;
}
//3.使用
//....
free(p);
p = NULL;
return 0;
}
5. Common errors in dynamic memory
- Dereference operation on NULL pointer
- Out-of-bounds access to dynamically opened space
- Use free release for non-dynamically allocated memory
- Use free to release a part of dynamically allocated memory
- Release the same dynamic memory multiple times
- Dynamically allocated memory and forgets to release it (memory leak)
6. Analysis of classic written test questions on dynamic memory
- Question 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 a value transfer and does not actually open up space for str. str is still NULL.
- Question 2
char* GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
printf(str);
}
The p variable life cycle is within the GetMemory function. The function ends and the variable is destroyed. Using the address of a variable that has been destroyed has unpredictable results
3. Question three
void Test(void)
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str);
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
The space pointed to by str is released, then str is a wild pointer, but str still points to that memory space; copy world to str, that isAccessed illegally。
7. Flexible array
- What is a flexible array
Maybe you have never heard of the concept of flexible array, but it does exist. In C99,in structure's最后⼀个元素
is allowed to be an array of unknown size, which is called a "flexible array" member.
struct s
{
int i;
char ch;
int a[]; //int a[0]
};
where a is a flexible array.
- Characteristics of flexible arrays
- before flexible array members in structureMust be at least oneother members.
- The size of this structure returned by sizeofMemory excluding flex arrays。
- The structure containing flexible array members usesmalloc () function to dynamically allocate memory, and the allocated memory shouldLarger than the size of the structure, to accommodate the expected size of the flex array.
- Use of flexible arrays
How can we implement the above code if we don't use flexible arrays?
Although the purpose can be achieved without using flexible arrays, there are two benefits to using flexible arrays:
- Convenient memory release
If our code is in a function used by others, you make two memory allocations and return the entire 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 to be free, so you cannot expect the user to discover this. Therefore, if we allocate the memory of the structure and the memory required by its members at once, and return a structure pointer to the user, the user can free all the memory once.
- Good for access speed
Continuous memory is beneficial to improving access speed and reducing memory fragmentation.
8. Memory area division in C/C++
- stack area
Stack area (stack): When executing a function, the storage units of local variables within the function can be created on the stack, and these storage units are automatically released when the function ends. The stack memory allocation operation is built into the instruction set of the processor and is very efficient, but the allocated memory capacity is limited.The stack area mainly stores local variables, function parameters, return data, return addresses, etc. allocated for running functions.。
- Heap area
Heap area (heap): Generally allocated and released by the programmer. If the programmer does not release it, it may be recycled by the OS when the program ends. The allocation method is similar to a linked list.
- static area
Data segment (static area): stores global variables and static-modified variables. It is released by the system after the program ends.
- code snippet
Code segment: stores the function body (class member function and global function)Binary code。
That’s it for this sharing! Please correct any errors.