【C语言】动态内存管理相关函数的使用和注意事项

目录

1.malloc和free函数的使用方法

2.calloc函数的使用方法

3.realloc函数的使用方法

4.动态内存管理的注意事项

1.对NULL指针的解引用操作

2.对动态空间开辟的越界访问

3.对非动态开辟内存使用ferr释放

4.使用free释放使用动态开辟内存的一部分

5.对同一块内存多次释放

6.动态开辟内存忘记释放(内存泄漏)


1.malloc和free函数的使用方法

malloc函数是动态内存分配函数,用于在堆内存上分配指定大小的内存块。它的使用方法如下:

  1. 引入stdlib.h头文件,该头文件包含了malloc函数的声明。
  2. 调用malloc函数,并传入要分配的内存大小作为参数。函数返回一个指向分配内存的指针。
  3. 使用返回的指针来访问分配的内存,并进行必要的操作。
  4. 使用完毕后,需要调用free函数释放内存。

free函数用于释放由malloc函数分配的内存。它的使用方法如下:

  1. 引入stdlib.h头文件,该头文件包含了free函数的声明。
  2. 调用free函数,并传入要释放的内存块的指针作为参数。

需要注意的是,使用malloc函数分配的内存必须在使用完成后调用free函数释放,以防止内存泄漏。另外,free函数只能释放由malloc函数分配的内存块,对于其他类型的指针或已经释放过的内存块,调用free函数可能导致未定义的行为。

下面是演示代码:

#include
#include
int main()
{
	int num = 0;
	scanf("%d", &num);
	int* p = NULL;
	p = (int*)malloc(num*(sizeof(int)));
	int i = 0;
	if (p != NULL)//判断指针是否为空
	{
		for (i = 0; i < 5; i++)
		{
			*(p + i) = i + 1;
			printf("%d", *(p + i));
		}
	}
	free(p);//释放p所指向的动态内存
	p = NULL;
	return 0;
}

2.calloc函数的使用方法

calloc函数用于分配内存空间,并将每个字节都初始化为0。 该函数的使用方法如下:

  1. 包含头文件:#include
  2. 函数原型:void* calloc(size_t num, size_t size); 参数num表示要分配的元素个数,size表示每个元素的大小。
  3. 调用函数并将返回的指针赋值给一个指针变量,例如: int* arr = (int*)calloc(10, sizeof(int)); 这样就分配了一个包含10个int类型元素的数组,并将其指针赋值给arr。
  4. 使用分配的内存空间进行操作,例如: for (int i = 0; i < 10; ++i) { arr[i] = i + 1; } 这样就将数组arr的每个元素依次赋值为1、2、3、...、10。
  5. 释放内存空间,使用free函数将之前分配的内存空间释放掉,例如: free(arr); 这样就释放了之前分配的数组arr所占用的内存空间。 注意事项:
  • 分配的内存空间必须通过free函数手动释放,否则可能会导致内存泄漏。
  • 分配的内存空间被初始化为0,如果不需要初始化为0,可以使用malloc函数代替。

下面是代码演示:

#include
#include
int main()
{
	int num = 0;
	scanf("%d", &num);
	int* p = NULL;
	p = (int*)calloc(num, sizeof(int));
	int i = 0;
	if (p != NULL)//判断指针是否为空
	{
		for (i = 0; i < 5; i++)
		{
			*(p + i) = i + 1;
			printf("%d", *(p + i));
		}
	}
	free(p);//释放p所指向的动态内存
	p = NULL;
	return 0;

3.realloc函数的使用方法

realloc函数用于重新分配内存空间。它可以用于扩大或缩小已分配的内存块。

realloc的使用方法如下:

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

其中,ptr是之前分配的内存块的指针,size是重新分配的内存块的大小。

如果ptr为NULL,那么realloc的行为就相当于malloc,即分配一块新的内存块。

如果size为0,那么realloc的行为就相当于free,即释放之前分配的内存块。

如果ptr和size都不为0,那么realloc将尝试重新分配size大小的内存块,并将之前分配的内存块内容复制到新的内存块中。如果重新分配失败,realloc将返回NULL,并保持之前分配的内存块不变。

需要注意的是,realloc返回的指针可能与之前的ptr不同,因此在使用之前需要将返回的指针赋给新的变量。

下面是一个realloc的使用示例:

#include
#include
int main()
{
	int* ptr = (int*)malloc(20);
	if (ptr != NULL)
		;  //执行语句
	else
		return 1;
	int* p = NULL;
	p = realloc(ptr, 10 * sizeof(int));//扩大ptr动态内存的空间
	if (p != NULL)
	{
		ptr = p;
	}
	free(ptr);//释放ptr动态内存
	ptr = NULL;
	p = NULL;
	return 0;
}

4.动态内存管理的注意事项

1.对NULL指针的解引用操作

void text()
{
	int* p = (int*)malloc(INT_MAX / 4);
	*p = 20;
	free(p);
}
int main()
{
	text();
	return 0;
}

如果p为NULL,因为NULL是不能被解引用的,就会出现问题,所以我们要判断p是否为NULL.

#include
#include
void text()
{
	int* p = (int*)malloc(INT_MAX / 4);
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	*p = 20;
	free(p);
	p = NULL;
}
int main()
{
	text();
	return 0;
}

2.对动态空间开辟的越界访问

void text()
{
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	int i = 0;
	for (i = 0; i <= 10; i++)
	{
		*(p + i) = i;//当i是10的时候会发生越界访问
	}
	free(p);
	p = NULL;
}
int main()
{
	text();
	return 0;
}

如果这样写,就会发生越界访问,导致程序崩溃。

3.对非动态开辟内存使用ferr释放

我们知道ferr只能释放动态内存,而不能去释放其他的内存。

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

如果这样写,也会程序崩溃。

4.使用free释放使用动态开辟内存的一部分

#include
#include
int main()
{
	int* p = (int*)malloc(100);
	p++;
	free(p);
	return 0;
}

这样也会发生错误。

5.对同一块内存多次释放

#include
#include
int main()
{
	int* p = (int*)malloc(100);
	free(p);
	free(p);
	return 0;
}

这样也会发生错误。

6.动态开辟内存忘记释放(内存泄漏)

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

所以我们在使用malloc等动态内存函数时一定要使用free来释放动态开辟的空间。

你可能感兴趣的:(C语言笔记,c语言,c++)