57.malloc、realloc、calloc的区别

发布时间 2023-07-04 19:51:54作者: CodeMagicianT

57.malloc、realloc、calloc的区别

malloc、realloc和calloc是C语言中的内存分配函数,它们有以下区别:

1.内存来源:malloc和realloc分配的内存空间位于堆中,而calloc在分配内存空间后会将其每一位都初始化为零,它也被称为“零初始化内存分配器”。

2.参数不同:malloc函数的参数是需要的内存空间的大小,返回的是void指针。realloc函数的参数是原有的空间地址和新申请的地址长度,它会根据需要调整内存块的大小,返回的是void指针。calloc函数的参数是申请地址的元素个数和单位元素长度,它在分配内存空间后会将其每一位都初始化为零,返回的也是void指针。

3.是否需要释放:malloc、realloc和calloc分配的内存都需要通过free函数来释放,但realloc在进行内存调整时,如果成功则返回调整后的内存块的地址,如果失败则返回NULL,并没有释放原来的内存块。

4.内存泄漏问题:如果程序在运行过程中malloc了内存空间,但是没有使用free函数来释放,就会造成内存泄漏。内存泄漏可能会导致系统可用内存不断减少,但当程序退出时,操作系统会回收所有资源,所以适当的重启程序有时可以缓解这个问题。

总结来说,malloc、realloc和calloc的主要区别在于它们所分配的内存来源、参数的不同以及它们在内存分配失败和处理内存泄漏问题上的行为。在编写C程序时,要根据具体需求和上下文来选择合适的内存分配函数。

以上参考阿秀

malloc、realloc、calloc的使用

1.malloc函数

作用:用于在堆区申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址

malloc 函数是一个用于在 C 语言中动态分配内存的函数。它允许你在程序运行时根据需要分配内存,而不是在编译时就确定好内存的大小。

以下是 malloc 函数的使用方法:

1.包含头文件:malloc 函数属于标准库的一部分,因此需要包含 <stdlib.h> 头文件才能使用它。

2.调用 malloc 函数:malloc 函数接受一个参数,表示要分配的内存大小(以字节为单位)。它返回一个指向分配内存的指针,如果分配失败则返回 NULL

int *ptr;  
ptr = (int*) malloc(sizeof(int));

在上面的示例中,我们使用 malloc(sizeof(int)) 分配了一个整型变量大小的内存空间。

3.使用分配的内存:一旦成功分配了内存,你就可以使用指针 ptr 来访问分配的内存空间。你可以将值存储在其中,读取其中的值,或者对其进行其他操作。

4.释放内存:当你不再需要分配的内存时,应该使用 free 函数来释放它,以便系统可以重新使用它。

free(ptr);  // 释放之前分配的内存空间

2.calloc函数

calloc 函数是 C 语言中的一个函数,用于动态地分配内存空间,并将分配的内存空间初始化为零。它与 malloc 函数类似,但 calloc 函数在分配内存时会自动将内存清零,因此可以避免在使用 malloc 分配的内存时需要手动清零的问题。

以下是 calloc 函数的使用方法:

1.包含头文件:calloc 函数属于标准库的一部分,因此需要包含 <stdlib.h> 头文件才能使用它。

#include <stdlib.h>

2.调用 calloc 函数:calloc 函数接受两个参数,第一个参数表示要分配的元素个数,第二个参数表示每个元素的大小(以字节为单位)。它返回一个指向分配内存的指针,如果分配失败则返回 NULL

int *ptr;  
ptr = (int*) calloc(10, sizeof(int));

在上面的示例中,我们使用 calloc(10, sizeof(int)) 分配了一个包含 10 个整型变量的内存空间,并将其初始化为零
3.使用分配的内存:一旦成功分配了内存,你就可以使用指针 ptr 来访问分配的内存空间。你可以将值存储在其中,读取其中的值,或者对其进行其他操作。

*ptr = 10;  // 将整数值 10 存储到分配的内存中  
printf("*ptr = %d\n", *ptr);  // 打印出分配的内存中的值

4.释放内存:当你不再需要分配的内存时,应该使用 free 函数来释放它,以便系统可以重新使用它。

free(ptr);  // 释放之前分配的内存空间

释放内存后,不应再使用指向已释放内存的指针。

注意事项:

  • malloc 函数一样,分配的内存必须在使用之前进行初始化,否则其内容是未定义的。
  • 在使用 calloc 分配的内存时,应始终检查返回的指针是否为 NULL,以避免分配失败导致的问题。
  • calloc 分配的内存会比 malloc 多一些额外的开销用于存储每个元素的字节数和元素个数等信息。因此,如果你只需要分配单个元素的空间并且不需要清零功能,使用 malloc 可能更加高效。

3.realloc函数(我发现CSDN等博客几十个文章都没说清楚,甚至很多说错了)

作用:当malloc函数或者calloc函数申请的空间或者数组的空间不够大或太大时就可以用realloc函数对空间的大小进行调整。

头文件:#include <stdlib.h> 有些编译器需要#include <malloc.h>,在TC2.0中可以使用alloc.h头文件

原型

 void *realloc(void *mem_address, unsigned int newsize);

realloc函数的作用是在已经分配的内存区域中重新分配一块指定大小的空间,如果原有的内存区域不够,则会重新分配一个更大的内存区域。其实现原理如下:

当newsize大于旧地址的容量时,可对旧地址进行扩容操作,规则如下:
1.首先考虑就近扩容,新的内存区域和旧的内存区域的起始地址相同,即新地址和就地址相同,同时保留旧的内存区域的数据成员,但新内存的容量是newsize。
2.当就近扩容无法进行,即无法就近申请一块newsize的连续的新地址,此时将申请一块新的容量为newsize的地址,然后将原有数据从头到尾拷贝到新的内存区域。

realloc() 函数用于重新分配之前通过 malloc()calloc()realloc() 分配的内存块。它接受两个参数:第一个参数是指向要重新分配的内存块的指针,第二个参数是要为新的内存块分配的字节数。

以下是 realloc() 函数的使用方法:

  1. 首先,确保你已经通过 malloc()calloc()realloc() 分配了一个内存块,并将其地址存储在一个指针变量中。
  2. 使用 realloc() 函数来重新分配内存块。将指针变量作为第一个参数,将要为新的内存块分配的字节数作为第二个参数。例如:
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)

int main()
{
	int current_size = 10;
	int* ptr = (int*)malloc(current_size * sizeof(int));  // 分配一个包含10个整数的内存块  
	// ... 在内存块中进行操作  
	for (int i = 0; i < 10; i++)
	{
		ptr[i] = i;
	}
	printf("当前分配内存空间大小:%d\n", current_size);
	printf("当前分配内存空间地址:%X\n", ptr);
	printf("当前分配空间保存的值:");
	for (int i = 0; i < 10; i++)
	{		
		printf("%d ", ptr[i]);
	}
	printf("\n=======================================================\n");

	int new_size = 20;  // 重新分配更大的内存块  

	int* new_ptr = (int*)realloc(ptr, new_size * sizeof(int));
	if (new_ptr != NULL) // 检查 realloc() 是否成功  
	{
		ptr = new_ptr;  // 将指针指向新的内存块 
	}
	else
	{
		// 处理重新分配失败的情况  
		printf("处理重新分配失败的情况\n");
	}

	printf("新分配内存空间大小:%d\n", new_size);
	printf("新分配内存空间地址:%X\n", new_ptr);
	printf("新分配空间保存的值:");
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", new_ptr[i]);
	}
	//free(ptr);//err
	free(new_ptr);
	printf("\n=======================================================\n");
	return 0;
}

输出:

当前分配内存空间大小:10
当前分配内存空间地址:3E15C950
当前分配空间保存的值:0 1 2 3 4 5 6 7 8 9
=======================================================
新分配内存空间大小:20
新分配内存空间地址:3E153390
新分配空间保存的值:0 1 2 3 4 5 6 7 8 9

注意以下几点:

VS2022中,X86模式下,分三种情况(实际也可以分为2种:成功和失败)

●如果重新分配的空间小于原来空间(肯定成功),则realloc() 函数将返回指向原来内存块的指针

●如果重新分配的空间大小不是很大,也就是当前的指针指向的内存段后面有需要的内存空间,则直接扩展这段内存空间,realloc()将返回原指针

●如果重新分配的空间大小是很大,则分配失败返回NULL

在VS2022中,X64模式下

●如果重新分配成功,存在两种情况realloc() 函数将返回一个指向新的内存块的指针(地址与原来不同)。你可以使用这个指针来访问新的内存块。

●如果重新分配失败,realloc() 函数将返回 NULL。在这种情况下,你需要保留之前的内存块,并处理重新分配失败的情况。

3.一旦你完成了对新内存块的操作, free() 函数释放之前和之后分配的内存块不能同时进行。例如:

free(ptr);  // 释放之前分配的内存块
free(new_ptr);