[C Language] Dynamic memory management, detailed! ! !


add link description

foreword

Hello everyone, after a few days, Xiaofan came to share C language learning with you again. Today, I will share with you my understanding of dynamic memory management! ! !

First, why there is dynamic memory allocation

For the space allocated on the stack:

  1. The space allocation size is fixed.
  2. When the 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 above situation. Sometimes the size of the space we need can only be known when the program is running, so the way to open up space when compiling the array cannot be satisfied

At this time, it is necessary to open up the rectangular dynamic memory in the heap area

2. Introduction of dynamic memory development function

1.malloc

Let’s take a look at the description of him in the library:
insert image description here

Function function: open up a memory block
Parameter size_t: the number of bytes to be applied
Return value: the application fails to return a null pointer, the application returns a pointer to the first address of the application space Header file: stdlib.h Note
: the type of the returned pointer is void* , At this time, you need to convert the pointer to the type you want, which is convenient for access and dereferencing. The space requested by malloc is continuous, but the use of malloc is discontinuous for multiple mallocs
.

int main()
{
    
    
	int*p=(int*) malloc(40);//申请了40个字节,强制转化为int*类型指针
	if (p == NULL)//如果返回空指针的话,申请失败
	{
    
    
		perror("malloc:");//打印错误信息
		return 1;//非正常退出
	}
	for (int i = 0; i < 10; i++)
	{
    
    
		*(p + i) = i;//对每一个四个字节大小的元素赋值,这里*(p+i)的本质就是p[i];
		printf("%d", *(p + i));//打印每个元素
	}
	return 0;//程序正常退出


}

2.calloc

Let’s take a look at the description of it in the library:
insert image description here
Function: Apply for an array in memory, and initialize it to 0;
Parameters: size_t num The number of elements in the application array, size_t size The byte size of each element
Return value: Application failed A null pointer is returned, and the application returns a pointer pointing to the first address of the application space Header file: stdlib.h
Use of calloc function:

int main()
{
    
    
	int i = 0;
	int*p=(int*) calloc(10,sizeof(int));//申请10个元素,每个元素字节大小4
	if (p == NULL)//如果返回空指针的话,申请失败
	{
    
    
		perror("calloc:");//打印错误信息
		return 1;//非正常退出
	}
	for (int i = 0; i < 10; i++)
	{
    
    
		
		printf("%d ", *(p + i));//打印初始化的值
	}
	free(p);
	p = NULL;
    return 0;


}

insert image description here
The difference between malloc and calloc:
the difference from the function malloc is that calloc will initialize each byte of the requested space to all 0s before returning the address

3.realloc

Let’s take a look at the description of it in the library:
insert image description here
Function: Memory block expansion
Parameters: The first parameter receives the first address of the memory block to be expanded, and the total byte size after expansion (including the original byte size)
Header file: stdlib .h
The initial expansion space is empty, then the usage of realloc and malloc is exactly the same
Return value: the first address of the expanded space
insert image description here
insert image description here
Usage of realloc function:

int main()
{
    
    
	int* p = (int*)malloc(40);//申请了40个字节,强制转化为int*类型指针
	if (p == NULL)//如果返回空指针的话,申请失败
	{
    
    
		perror("malloc:");//打印错误信息
		return 1;//非正常退出
	}
	for (int i = 0; i < 10; i++)//循环打印扩容前的元素
	{
    
    
		*(p + i) = i;
		printf("%d ", *(p + i));
	}
	int* ptr = (int*)realloc(p, 80);//原空间够用ptr==p,不够用的话ptr存放新地址
	if (ptr != NULL)//扩容成功
	{
    
    
		p = ptr;//原空间够用ptr==p,不够用的话ptr存放新地址,重新将新地址给p
	}
	for (int i = 10; i < 20; i++)//扩容后新空间的
	{
    
    
		*(p + i) = i;
		printf("%d ", *(p + i));
	}

    free(p);
	p = NULL;
	
	return 0;
}

insert image description here

4.free

Let’s take a look at the description of it in the library:
insert image description here
Function: Release the memory block
Parameter: Pointer to receive the first address of the memory block to be released
Header file: stdlib.h
Return value: None

Note:
When the requested space pointed to by p is released, the p pointer points to a random location, and p becomes a wild pointer, so we need to set it to empty after release! ! !

If we do not release the memory requested by the dynamic memory, the program ends, and the dynamically requested memory is automatically reclaimed by the operating system. If the free function is not used to release the requested space, it will remain in the heap until the end of the program, causing memory leaks

3. Common errors in dynamic memory development

1. Dereferencing NULL by mistake

for example:

int main()
{
    
    
	int* p = (int*)malloc(1000);
	int i = 0;
	if (p ==NULL)
	{
    
    
		return 1;
	}
	for (i = 0; i < 250; i++)
	{
    
    
		*(p + i) = i;
	}
	free(p);
	p = NULL;
	return 0;
}

When allocating memory fails, it will return empty, which is easy to cause this error.
Solution: Make a judgment after opening up the memory, such as the if judgment in the above code

2. An out-of-bounds access is made to the dynamically opened space

int main()
{
    
    
	int* p = (int*)malloc(100);
	int i = 0;
	if (p ==NULL)
	{
    
    
		return 1;
	}
	for (i = 0; i <=25; i++)//越界访问
	{
    
    
		*(p + i) = i;
	}
	free(p);
	p = NULL;
	return 0;
}

Solution: Manually check whether it is out of bounds

3. The free operation is performed on the non-dynamically allocated memory

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

4. Only free part of the dynamically allocated memory

int main()
{
    
    
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
    
    
		return 1;}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		*p = i;
		p++;
    }
	free(p);
	p = NULL;
	return 0;
}

Solution:
Do not change the pointer variable that saves the first address of the dynamically opened space, you can use the method of intermediate variables when using it! ! !
For example:

int main()
{
    
    
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
    
    
		return 1;


	}
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		*(p+i)= i;
		printf("%d ", *(p + i));
    }
	free(p);
	p = NULL;

	return 0;
}

5. Free the space memory that has been released multiple times

int main()
{
    
    
	int* p = malloc(40);
	if (p == NULL)
	{
    
    
		return 1;
	}
	free(p);
	free(p);
	p = NULL;
	return 0;
}

Four. Summary

This time the content is shared here. If you think it is helpful to you, please give it a thumbs up. If there is something wrong with the sharing, please correct me. Thank you for reading! ! !

Guess you like

Origin blog.csdn.net/m0_71214261/article/details/132482039