The article directories

  • Dynamic memory management
    • preface
    • Why does dynamic memory allocation exist?
    • Second, the introduction of dynamic memory functions
    • 1. Introduction of malloc function
    • 2. Introduction of free function
    • 3. Use malloc function and free together
    • 4. Introduction of Calloc function
    • 5. Use of calloc function
    • 6. Introduction of Realloc functions
    • 7. Use of Realloc functions
    • Common dynamic memory errors
    • 1. Dereference the NULL pointer
    • 2. Access the dynamically allocated memory
    • 3. Free the memory that is not dynamically created
    • 4. Use free to free part of dynamic memory
    • 5. Release the same dynamic memory block multiple times
    • 6. Dynamically open the memory and forget to release it
    • Four, dynamic memory classic pen test questions
    • 1. A practice
    • 2. Exercise two
    • Three (3) practice
    • 4. Practice in four
    • Five, C/C++ program memory development
    • Flexible arrays
    • 1. Characteristics of flexible arrays
    • 2. Use of flexible arrays
    • 3. Advantages of flexible arrays
    • After the

Dynamic memory management

\

preface

\

Currently we know how we use memory \

1. Create a variable

int a=0;
Copy the code

Global variables – Open up memory in static areas

Local variable – Opens up memory in the stack area

2. Create an array

An array is a contiguous memory space

int arr[10] =0;
Copy the code

Create global array – free up memory in static area

Create local arrays – create memory in the stack area

3. Parameters and arguments of a function

There are also some other data that occupy the memory space. The specific memory usage is as follows:

Why does dynamic memory allocation exist?

\

We have mastered the memory opening methods are:

int val =20;         // Create 4 bytes in stack space
char arr[10] = {0};   // Create a contiguous space of 10 bytes in stack space
Copy the code

But there are two characteristics of the above way of opening up space:



Here’s a concrete example:

char arr[20] = {0};
Copy the code

\

We are given a contiguous memory space that can hold 20 bytes, so if we have 10 CHArs to store, we will waste the remaining memory space, and if we have 30 CHars to store, the ARR array will not have enough space to store our data.

But the need for space goes beyond that. Sometimes the amount of space we need is not known until the program is running, so the way the array makes space at compile time is not sufficient. At this point, we can only try dynamic memory open.

\

Second, the introduction of dynamic memory functions

\

1. Introduction of malloc function

\

The c language provides a dynamic memory opening function:



The open () function opens a block of memory

Function argument: the size of the space in bytes

Function return type: void * null pointer type

Specific requirements of the function:

2. Introduction of free function

\

C language also provides another function free, specifically for dynamic memory release and reclamation, function prototype is as follows.



Specific requirements of the function:



When dynamically requested space is no longer used, it should be returned to the operating system.

So we need to release the space malloc requested

free(p);
p=NULL;
Copy the code

\

Since P is released, the space pointed to by P is meaningless, but the content of that space is still there, so P still has the ability to find this space. In order to avoid the wrong use of this space, we set P =NULL and assign it as a NULL pointer, so that the P pointer is truly disconnected from this space.

\

3. Use malloc function and free together

\

Note: both the malloc and free functions reference the <stdlib.h> header file

#include <stdio.h>
#include <stdlib.h>

int main(a)
{
	// int arr[10] = { 0 };
	int *p = (int*)malloc(10 * sizeof(int));// Create a contiguous space of 10 ints
	if (p == NULL)
	{
		printf("Failed to open memory \n");
	}
	else
	{
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			p[i] = i;
		}
		for (i = 0; i < 10; i++)
		{
			printf("%d ", p[i]); }}free(p);
	p=NULL;
	return 0;
}
Copy the code

\

4. Introduction of Calloc function

\

C language also provides a function called calloc, calloc function is also used for dynamic memory. The prototype is as follows:

The open () function opens a contiguous space in memory and initializes each byte in the space to 0

Function argument First argument: number of elements second argument: size in bytes for each element

Function return type: void * null pointer type

Specific requirements of the function:

\

5. Use of calloc function

\

#include <stdio.h>
#include <stdlib.h>

int main(a)
{
	//int arr[10] = { 0 };
	int *p = (int*)calloc(10.4);// Create a contiguous space of 40 bytes
	if (p == NULL)
	{
		printf("Failed to open memory \n");
	}
	else
	{
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			printf("%d ", p[i]); }}free(p);
	p=NULL;
	return 0;
}
Copy the code

The result of executing the code is as follows:



Memory displays initialization results:

So if we need to initialize the contents of the requested memory space, we can easily use the calloc function to complete the task.

\

6. Introduction of Realloc functions

Function Reallocate memory space to adjust the size of the dynamic memory space

Function arguments: The first argument is the address of the previously opened memory block, and the second argument is the size of the adjusted space in bytes.

Function return type: void * null pointer type

Function specific functions:



Matters needing attention:



Realloc functions have two situations when adjusting the memory space:

Case one: there is not enough space after the original space

We want to be in the original memory location change memory size, but the back of the original memory block is not enough space, we extend the method is: on the heap space find another suitable size of contiguous space to use, and the original data in memory copy to come over, this function returns a new memory address. Note that in the process of finding a new space, the original memory is released, and we do not need to worry about memory leaks.

\

Case two: there is enough space after the original space

When we want to adjust the original memory space, to expand the memory directly after the original memory directly add space, the original space data does not change. The last return is the original address.

\

7. Use of Realloc functions

\

Here’s an example:

#include <stdio.h>
#include <stdlib.h>

int main(a)
{
	int * p = (int *)malloc(10 * sizeof(int));

	if (p == NULL)
	{
		printf("Failed to create space \n");
	}
	else
	{
		int i = 0;
		for (i = 0; i<10; i++)
		{
			p[i] = i;
		}
		for (i = 0; i<10; i++)
		{
			printf("%d ", p[i]); }} here one is created in the heap area40If we're running out of memory space, we want to make it bigger, make it bigger80The size of the space in bytesint* p2 = (int *)realloc(p,20*sizeof(int));

	if (p2 == NULL)
	{
		printf("Failed to open memory \n");
	}

	else
	{
		int i = 0;
		for (i = 10; i < 20; i++)
		{
			p[i] = i;
		}
		for (i = 10; i < 20; i++)
		{
			printf("%d ", p[i]); }}free(p2);
	p2 = NULL;

	return 0;
}
Copy the code

\

Common dynamic memory errors

\

1. Dereference the NULL pointer

int main(a)
{
	int *p = (int *)malloc(10 * sizeof(int));
	*p = 0;
	int i = 0;
	for (i = 0; i<10; i++)
	{
		printf("%d ", p[i]);
	}

	free(p);
	p = NULL;
	return 0;
}
Copy the code

A question for the code here is, if P =NULL, will the code work?

If p=NULL, the dereference operation is illegal and the editor will report an error.

\

2. Access the dynamically allocated memory

#include <stdio.h>
#include <stdlib.h>

int main(a)
{
	int *p = (int *)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		printf("Failed to open memory \n");
	}
	else
	{
		int i = 0;
		for (i = 0; i<20; i++)
		{
			p[i] = i;
		}
		for (i = 0; i<20; i++)
		{
			printf("%d ", p[i]); }}return 0;
}
Copy the code

We created 10 ints in the heap, but we started at the beginning of the memory and accessed 20 ints beyond the size of the heap. This is an out-of-bounds access, and the system will report an error.

\

3. Free the memory that is not dynamically created

#include <stdio.h>
#include <stdlib.h>

int main(a)
{
    int a=10;
    int *p=&a;
    free(p);
    p=NULL;
    return 0;
}
Copy the code

Code running results:

We emphasize that the free function can only free the dynamic memory we have created!

\

4. Use free to free part of dynamic memory

#include <stdio.h>
#include <stdlib.h>
int main(a)
{
	int *p = (int *)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		printf("Failed to open memory \n");
	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*p++;
	}
	free(p);
	p = NULL;
	return 0;
}
Copy the code

Here we should note:

The pointer to this memory keeps changing as we give p++



When we finally free (p), p does not point to the initial location of memory, so the space we created cannot be fully freed, resulting in memory leakage.

\

5. Release the same dynamic memory block multiple times

#include <stdio.h>

int main(a)
{
	int *p = (int *)malloc(100);
	free(p);
	free(p);   // Repeat release
	p=NULL;
	return 0;
}
Copy the code

Note: the same memory space can only be freed once

\

6. Dynamically open the memory and forget to release it

#include <stdio.h>

int main(a)
{
	int *p = (int *)malloc(100);
	if (NULL! = p) { *p =20;
	}
	while (1);
	return 0;
}
Copy the code

Note: Forgetting to free up dynamically opened space that is no longer in use can cause memory leaks.

Remember: dynamic space must be released, and the correct release.

\

Four, dynamic memory classic pen test questions

\

1. A practice

#include <stdio.h>
#include <stdlib.h>

void GetMemory(char *p)
{
	p = (char *)malloc(100);
}
void Test(void)
{
	char *str = NULL;
	GetMemmory(str);
	strcpy(str, "helloworld");
	printf(str);
}
int main(a)
{
	Test();
	return 0;
}
Copy the code

What is the result of the Test function?

The problem with this code:

The result is that the STR returned by GetMemory is still NULL, putting “Hello world” into the space pointed to by the NULL pointer, and the program inevitably crashes.

How to fix the code:

#include <stdlib.h>

void GetMemory(char **p)
{
	*p = (char *)malloc(100);
}
void Test(void)
{
	char *str = NULL;
	GetMemory(&str);
	strcpy(str, "hello world");
	printf(str);
	free(str);
	str = NULL;
}
int main(a)
{
	Test();
	return 0;
}
Copy the code

Display effect:

\

2. Exercise two

#include <stdio.h>
#include <stdlib.h>
char *GetMemory(void) 
{
   char p[] = "hello world";
   return p; 
}

void Test(void) 
{
   char *str = NULL;
   str = GetMemory();
   printf(str);
}
int main(a)
{
   Test();
   return 0;
}
Copy the code

What is the result of the Test function?

Problem in this code: illegal access to memory!

This is a classic return stack address problem

The function GetMemory () creates an array of p and returns the address of p. There is a problem with returning the address of the stack space inside the function. Local variables are automatically destroyed after leaving the function.

\

Three (3) practice

#include <stdio.h>
#include <stdlib.h>

void GetMemory(char **p, int num)
{
    *p = (char *)malloc(num);
}
void Test(void) 
{
   char *str = NULL;
   GetMemory(&str, 100);
   strcpy(str, "hello");
   printf(str);
}
int main(a)
{
   Test();
   return 0;
}
Copy the code

What is the result of the Test function?

Problem with code:

Memory leaks due to forgetting to free dynamically allocated memory

Correct code:

#include <stdio.h>
#include <stdlib.h>

void GetMemory(char **p, int num)
{
    *p = (char *)malloc(num);
}
void Test(void) 
{
   char *str = NULL;
   GetMemory(&str, 100);
   strcpy(str, "hello");
   printf(str);
   free(p);
   p=NULL;
}
int main(a)
{
   Test();
   return 0;
}
Copy the code

\

4. Practice in four

#include <stdio.h>
#include <stdlib.h>

void Test(void)
{
  char *str=(char *)malloc(100);
  strcpy(str,"hello");
  free(str);
  if(str! =NULL)
  {
      strcpy(str,"world");
      printf(str); }}int main(a)
{
   Test();
   return 0;
}
Copy the code

What is the result of the Test function?

Problems with this code:

After free (STR), we have freed the dynamic memory and returned it to the operating system. We can’t do anything with it, but p is not set to NULL, so STR still remembers the address of the dynamic memory that it pointed to. This memory no longer belongs to us, and we need to copy “world” into this memory. This is illegal access to memory.

So how do we make corrections?


#include <stdio.h>
#include <stdlib.h>

void Test(void)
{
  char *str=(char *)malloc(100);
  strcpy(str,"hello");
  free(str);
  str=NULL;
  if(str! =NULL)
  {
      strcpy(str,"world");
      printf(str); }}int main(a)
{
   Test();
   return 0;
}
Copy the code

\

Five, C/C++ program memory development





In fact, ordinary local variables are allocated space in the stack area, which is characterized by variables created there being destroyed out of scope.

However, static variables are stored in the data segment (the static section), which is characterized by variables created on it that are not destroyed until the end of the program, so the life cycle is longer.

\

Flexible arrays

You’ve probably never heard of flexible arrays, but they exist. In C99, the last element in the structure is allowed to be an array of unknown size, which is called a flexible array member.

Such as:

typedef struct st_type
{
	int i;
	int a[0];// A flexible array member
}type_a;
Copy the code

Error: failed to compile

typedef struct st_type
{
 int i;
 int a[];// A flexible array member
}type_a;
Copy the code

\

1. Characteristics of flexible arrays

Such as:

/ / code 1

typedef struct st_type
{
 int i;
 int a[0];// A flexible array member
}type_a;
printf("%d\n".sizeof(type_a);  // The output is 4
Copy the code

\

2. Use of flexible arrays

#include <stdlib.h>
#include <stdio.h>


/ / code 1
typedef struct st_type
{
	int i;
	int a[0];// A flexible array member
}type_a;

int main(a)
{
	int i = 0;
	type_a *p = (type_a *)malloc(sizeof(type_a)+100 * sizeof(int));

	p ->i=100;
	for (i = 0; i<100; i++)
	{
		p->a[i] = i;
	}
	free(p);
	p = NULL;
	return 0;
}
Copy the code

Such a flexible array member, A, is equivalent to obtaining a continuous space of 100 integer elements.

\

3. Advantages of flexible arrays

The type_A structure described above can also be designed as:

/ / code 2
typedef struct st_type
{
   int i;
   int *p_a; 
}type_a;
   type_a *p = malloc(sizeof(type_a));
   p->i = 100;
   p->p_a = (int *)malloc(p->i*sizeof(int));
// Business processing
  for(i=0; i<100; i++)
   {
     p->p_a[i] = i; 
   }
// Free up space
  free(p->p_a);
  p->p_a = NULL;
  free(p);
  p = NULL;
Copy the code

\

Code 1 and code 2 above can do the same thing, but the implementation of method 1 has two benefits: the first benefit is to facilitate memory freeing

If our code is in a function for someone else to use, you do a secondary memory allocation in it and return the entire structure to the user. The user calls free to free the structure, but the user doesn’t know that members of the structure also need free, so you can’t expect the user to find out. So, if we allocate the structure’s memory and its members’ memory all at once, and return the user a pointer to the structure, the user can do a free to free all of the memory.

\

The second benefit is that it facilitates access speed.

Continuous memory is good for improving access speed and reducing memory fragmentation. (Actually, I personally don’t think it’s that high, you can’t run away from it anyway and you have to use offset addition to address it.

\

Well, this is the end of dynamic memory management, I hope you can practice more…

Thank you !!!!


\

After the