[C language: dynamic memory management]

Insert image description here

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:

  1. The size of the opened space is fixed
  2. 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

Insert image description here
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
Insert image description here
When the parameter of the function is 0, it is a random value in vs2019
Insert image description here
Since the space is a program If someone applied for it, then who would be released in the end?

  1. The programmer releases it himself.
  2. 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:
Insert image description here

  • 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.

Insert image description here

3.calloc

Insert image description here
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.

Insert image description here

4.realloc

Insert image description here

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

  1. Dereference operation on NULL pointer
  2. Out-of-bounds access to dynamically opened space
  3. Use free release for non-dynamically allocated memory

Insert image description here

  1. Use free to release a part of dynamically allocated memory

Insert image description here

  1. Release the same dynamic memory multiple times

Insert image description here

  1. Dynamically allocated memory and forgets to release it (memory leak)

6. Analysis of classic written test questions on dynamic memory

  1. 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.
Insert image description here

  1. 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
Insert image description here

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

  1. 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.

  1. 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.
  1. Use of flexible arrays

Insert image description here

How can we implement the above code if we don't use flexible arrays?
Insert image description here

Although the purpose can be achieved without using flexible arrays, there are two benefits to using flexible arrays:

  1. 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.

  1. Good for access speed

Continuous memory is beneficial to improving access speed and reducing memory fragmentation.

8. Memory area division in C/C++

Insert image description here

  1. 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.

  1. 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.

  1. static area

Data segment (static area): stores global variables and static-modified variables. It is released by the system after the program ends.

  1. 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.

Guess you like

Origin blog.csdn.net/weixin_69380220/article/details/134909804