C language dynamic memory management

In the C language, when we use arrays, we often have such a problem: when the array is declared, the length of the array must be specified, and the memory it needs is allocated at compile time. Sometimes, the space we open up is too small to meet our needs, and sometimes it is too large, and the waste of space is serious. Then can we open up one space if we need one, and open up two spaces if we need two? At this time, you can only try to open up dynamic memory.

1. malloc function and free function

C language provides a function for dynamic development: malloc function. The header file is stdlib.h.

void* malloc (size_t size);

This function can apply for a continuous available space in the memory. If the opening is successful, it will return the pointer of the opened space, otherwise, it will return NULL. Therefore, when using malloc, be sure to check the return value of the function to avoid null pointer references. Since the malloc function does not know what type of space to open up, it is generally necessary to perform type conversion when using it.

The free function is used to release and reclaim dynamic memory. The header file is stdlib.h.

void free (void* ptr);

The free function can only release functions in dynamic memory. If the space pointed to is not dynamically allocated, the result of the free function is undefined.

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

int main(void)
{
	int* a = (int*)malloc(sizeof(int));//给a动态开辟空间
	
	free(a);
    a = NULL;
	return 0;
}
apply for space for a

free(a)

 The above example is just a simple illustration of the usage of the malloc function. It should be noted that in general, the return value of the malloc function must be checked, and at the same time, after the malloc function is used, it must be released in time. At the same time, the assignment to the referenced pointer is null. Otherwise, the above a will become a wild pointer, which will lead to illegal access problems when it is used again later.

2. calloc function

The function of the calloc function is to open up a space for num elements of size size, and initialize each byte of the space to 0. The only difference from the function malloc is that calloc will initialize each byte of the requested space to all 0s before returning the address.

void* calloc (size_t num, size_t size);

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

int main(void)
{
	int* p = (int*)calloc(10, sizeof(int));//给p动态开辟空间

	free(p);
	return 0;
}

3. realloc function

Sometimes after we use the malloc function, we find that the requested space is still too small, and sometimes it is too large. If we want to modify it again, we can use the realloc function at this time. The header file is stdlib.h.

void* realloc (void* ptr, size_t size);

 ptr is the memory address to be adjusted, size is the new size after adjustment. The return value is the starting position of the adjusted memory.

When the realloc function is adjusted, there are the following ways:

1. If there is enough space behind the original space, expand it directly.

2. Find another space that meets the requirements, copy the value of the original space, and return the new space address.

When the return result of the realloc function is used, it is necessary to judge whether the return value is NULL. 

 Fourth, common memory errors

1. Dereferencing a NULL pointer

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

void test()
{
	int* p = (int*)malloc(INT_MAX / 4);
	if (p != NULL)
	{
		*p = 20;//如果p的值是NULL,就会有问题,要进行判断
		printf("%d", *p);//20
	}
	else
	{
		printf("为空!");
	}

	free(p);
}

int main(void)
{
	test();
	return 0;
}

2. Cross-border access to dynamically developed 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);
}


int main(void)
{
	test();
	return 0;
}

The program will crash.

3. Free release the non-dynamically developed space

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

int main(void)
{
	test();

	return 0;
}

 

 4. Only release part of the dynamically opened memory

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

int main(void)
{
	test();

	return 0;
}

Same result as above.

5. Release the same piece of memory multiple times.

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

int main(void)
{
	test();

	return 0;
}

Still the same result.

6. Forget to release, causing memory leak.

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

The development of dynamic memory is developed on the heap, and the memory in it needs to be released manually. If it is not released, it may be automatically reclaimed by the system at the end of the final program.

The variables we usually write wait in the stack, data segment (stores global variables, static variables), etc. These do not need to be released manually, they have their own scope, and they will be automatically destroyed when they are out of this scope. The space opened up on the heap needs to be released manually.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324041796&siteId=291194637