05-C language advanced-dynamic memory management

1. Why do we need dynamic memory allocation?

The memory development method used earlier is to open up space on the stack, for example:

int val = 20;//在栈空间上开辟四个字节
char arr[10] = {
    
    0};//在栈空间上开辟10个字节的连续空间

However, the above-mentioned way of opening up space has two characteristics:

  • The size of the space is fixed.
  • When an array is declared, the length of the array must be specified, and the memory it needs is allocated at compile time .
    But the demand for space is not just the case above. Sometimes the size of the space we need can only be known when the program is running, and the way the array is compiled cannot be satisfied. At this time, you can only try dynamic storage and development.

Two, dynamic memory function introduction

2.1malloc

malloc is used to open up dynamic memory

void * malloc(size_t size);

This function applies for a continuously available space from the memory and returns a pointer to this space .

  • If you open up successful , it returns a good point to open up space pointer .
  • If the development fails , a NULL pointer is returned , so the return value of malloc must be checked .
  • The type of the return value is void *, so the malloc function does not know the type of space opened up, and the user decides it when it is used.
  • If the parameter size is 0, the behavior of malloc is undefined by the standard and depends on the compiler.

2.2 free

void free (void* ptr);

The free function is used to release dynamically allocated memory.

  • If the space pointed to by the parameter ptr is not dynamically opened up , the behavior of the free function is undefined .
  • If the parameter ptr is a NULL pointer, the function does nothing .
    Both malloc and free are declared in the stdlib.h header file. for example:
//申请5个整形字节的动态内存
int *p = (int *)malloc(5*sizeof(int));
//若返回值为空,则申请失败
if (NULL == p)
{
    
    
	printf("malloc error!\n");
	return 1;
}
//若申请成功,为每个元素赋值
for (int i = 0; i < 5; i++)
{
    
    
	p[i] = i;
}
printf("malloc success!\n");

//打印释放前p的地址
printf("before:%p\n",p);

//释放动态开辟的内存
free(p);

//打印释放后p的地址
printf("after:%p\n", p);

Insert picture description here
A few points to note here

  • As shown in the figure above, the address pointed to before and after free does not change, only the management relationship between the pointer and the corresponding memory is changed. Generally add another code to make the pointer NULL.
p = NULL;
  • As shown in the figure below, the released address space is obviously larger than the space at the time of application, because the pointer at the time of application contains other meta-information. It can be found that using malloc to apply for a small block of space is more expensive, so it is not recommended to apply for a small block of memory.
    Insert picture description here
    Insert picture description here

2.3 calloc

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

void* calloc (size_t num, size_t size);
  • The function of the function is to open up a space for num elements of size size, and initialize each byte of the space to 0 .
  • The difference with the function malloc is that calloc initializes each byte of the requested space to all 0s before returning the address . for example:
int *p = (int *)calloc(10, sizeof(int));
if (NULL != p)
{
    
    
	printf("success!\n");
}

free(p);
p = NULL;

Insert picture description here

2.4 realloc

The emergence of the realloc function makes dynamic memory management more flexible.
Sometimes we find that the space applied for in the past is too small, and sometimes we feel that the applied space is too large. In order to use the memory reasonably, we must make flexible adjustments to the size of the memory. The realloc function can adjust the size of the dynamically opened memory. Function prototype:

void * realloc(void * ptr, size_t size);
  • ptr is the memory address to be adjusted
  • new size after size adjustment
  • The return value is the adjusted memory starting position .
  • This function adjustment based on the original size of the memory space, but also to move the data in the original memory to the new space .
  • There are two situations when realloc adjusts the memory space:
    • Situation 1: There is enough space after the original space . In case 1, if you want to expand the memory, add space directly after the original memory, and the data in the original space will not change .
    • Situation 2: There is not enough space after the original space . Expansion method: Find another contiguous space of suitable size on the heap space to use. This function returns a new memory address . Due to the above two situations, the use of realloc function should be paid attention to. For example
      :
	int *ptr = malloc(100);
	if (ptr != NULL)
	{
    
    
		//业务处理
	}
	else
	{
    
    
		exit(EXIT_FAILURE);
	}
	//扩展容量
	//代码1
	ptr = realloc(ptr, 1000);//如果申请失败造成内存泄漏

	//代码2
	int*p = NULL;
	p = realloc(ptr, 1000);
	if (p != NULL)
	{
    
    
		ptr = p;
	}
	//业务处理
	free(ptr);

The problem with code 1 is that if the realloc application fails and returns a NULL pointer, the old space ptr is emptied, causing a memory leak and unable to find the original memory address.

Three, common dynamic memory errors

3.1 Dereference operations on NULL pointers

void test()
{
    
    
    int *p = (int *)malloc(INT_MAX/4);
    *p = 20;//如果p的值是NULL,就会有问题
    free(p);
}

If the requested space is large, the return value of malloc may be NULL

3.2 Out-of-bounds access to the dynamic open space

void test()
{
    
    
    int i = 0;
    int *p = (int *)malloc(10*sizeof(int));
    if(NULL == p)
    {
    
    
        exit(EXIT_FAILURE);
    }
    for(i=0; i<=10; i++)
    {
    
    
        *(p+i) = i;//当i是10的时候越界访问
    }
    free(p);
}

3.3 Use free release for non-dynamically opened memory

void test()
{
    
    
    int a = 10;
    int *p = &a;
    free(p);//错误
}

3.4 Use free to release a part of dynamically opened memory

void test()
{
    
    
    int *p = (int *)malloc(100);
    p++;
    free(p);//p不再指向动态内存的起始位置
}
 

3.5 Release the same dynamic memory multiple times

void test()
{
    
    
    int *p = (int *)malloc(100);
    free(p);
    free(p);//重复释放
}

3.6 Dynamically open memory and forget to release (memory leak)

void test()
{
    
    
    int *p = (int *)malloc(100);
    if(NULL != p)
    {
    
    
        *p = 20;
    }
}
 
int main()
{
    
    
    test();
    while(1);
}

Guess you like

Origin blog.csdn.net/qq_40076022/article/details/110109813