区别是什么:

ptr = malloc(MAXELEMS * sizeof(char *));

And:

ptr = calloc(MAXELEMS, sizeof(char*));

什么时候使用calloc优于malloc或反之亦然?


当前回答

还有一个没有提到的区别:大小限制

void *malloc(size_t size)只能分配到SIZE_MAX。

Void *calloc(size_t nmemb, size_t size);可以分配大约SIZE_MAX*SIZE_MAX。

在许多具有线性寻址的平台中,不经常使用此功能。这样的系统用nmemb * size <= SIZE_MAX限制calloc()。

考虑一种名为disk_sector的512字节类型,代码希望使用大量扇区。在这里,代码最多只能使用SIZE_MAX/sizeof disk_sector扇区。

size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);

考虑下面允许更大分配的情况。

size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);

现在,这样一个系统能否提供如此大的分配是另一回事。今天大多数人都不会。然而,当SIZE_MAX为65535时,这种情况已经发生了很多年。根据摩尔定律,这种情况将在2030年左右发生,某些内存模型SIZE_MAX == 4294967295,内存池为100 gb。

其他回答

有两个不同之处。 首先,是参数的数量。Malloc()接受一个参数(以字节为单位的内存需求),而calloc()需要两个参数。 其次,malloc()不会初始化分配的内存,而calloc()会将分配的内存初始化为ZERO。

Calloc()分配一个内存区域,长度将是其参数的乘积。calloc用0填充内存,并返回指向第一个字节的指针。如果它不能找到足够的空间,它返回一个NULL指针。

语法:ptr_var = calloc(no_of_blocks, size_of_each_block); 即ptr_var = calloc(n, s);

malloc()分配REQUSTED SIZE的单个内存块,并返回指向第一个字节的指针。如果它无法找到所请求的内存量,它返回一个空指针。

语法:ptr_var = malloc(Size_in_bytes); malloc()函数有一个参数,即分配的字节数,而calloc()函数有两个参数,一个是元素的数量,另一个是为每个元素分配的字节数。另外,calloc()将分配的空间初始化为0,而malloc()不会。

Calloc()为您提供了一个零初始化的缓冲区,而malloc()则保留未初始化的内存。

对于大的分配,主流操作系统下的大多数calloc实现将从操作系统获得已知的零页(例如通过POSIX mmap(MAP_ANONYMOUS)或Windows VirtualAlloc),因此不需要在用户空间中编写它们。这就是普通malloc从操作系统获取更多页面的方式;calloc只是利用了操作系统的保证。

这意味着calloc内存仍然可以是“干净的”和惰性分配的,写时复制映射到系统范围的共享物理零页。(假设系统有虚拟内存。)例如,在Linux上进行性能实验,效果是显而易见的。

一些编译器甚至可以为你优化malloc + memset(0)为calloc,但如果你想要零内存,最好只在源代码中使用calloc。(或者,如果您试图预先出错以避免以后出现页面错误,那么这种优化将使您的尝试失败。)

如果你不打算在写内存之前读取内存,使用malloc,这样它就可以(潜在地)从内部空闲列表中给你脏内存,而不是从操作系统中获取新页面。(或者不是将空闲列表上的内存块归零以获得少量分配)。


如果没有操作系统,或者它不是一个多用户操作系统,那么calloc的嵌入式实现可能会把它自己的内存设置为0,以阻止进程之间的信息泄漏。

在嵌入式Linux上,malloc可以mmap(MAP_UNINITIALIZED|MAP_ANONYMOUS),这只对一些嵌入式内核启用,因为它在多用户系统上是不安全的。

在<stdlib.h>标头中声明的calloc()函数比malloc()函数提供了几个优点。

它将内存分配为一定数量的给定大小的元素 它初始化所分配的内存,这样所有的位都是 零。

malloc和calloc都分配内存,但calloc将所有位初始化为0,而malloc则不这样做。

可以说,Calloc相当于malloc + memset + 0(其中memset将指定的内存位设置为0)。

因此,如果不需要初始化为0,那么使用malloc可能会更快。

一个不太为人所知的区别是,在具有乐观内存分配的操作系统(如Linux)中,由malloc返回的指针直到程序实际接触它时才得到实际内存的支持。

calloc确实会接触内存(它会在内存上写0),因此您可以确定操作系统正在用实际的RAM(或swap)支持分配。这也是为什么它比malloc慢的原因(它不仅必须将它归零,操作系统还必须通过交换其他进程来找到合适的内存区域)

例如,请参阅这个SO问题以进一步讨论malloc的行为