区别是什么:

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

And:

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

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


当前回答

Calloc一般是malloc+memset为0

显式使用malloc+memset通常会稍微好一点,特别是当你在做以下事情时:

ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));

That is better because sizeof(Item) is know to the compiler at compile time and the compiler will in most cases replace it with the best possible instructions to zero memory. On the other hand if memset is happening in calloc, the parameter size of the allocation is not compiled in in the calloc code and real memset is often called, which would typically contain code to do byte-by-byte fill up until long boundary, than cycle to fill up memory in sizeof(long) chunks and finally byte-by-byte fill up of the remaining space. Even if the allocator is smart enough to call some aligned_memset it will still be a generic loop.

一个值得注意的例外是,当您对一个非常大的内存块(一些power__2kb)执行malloc/calloc时,在这种情况下,可以直接从内核进行分配。由于操作系统内核通常会出于安全原因将它们放弃的所有内存归零,足够聪明的calloc可能只返回内存,而不进行额外的归零。同样,如果你只是分配一些你知道很小的东西,那么在性能方面使用malloc+memset可能会更好。

其他回答

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

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。

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),这只对一些嵌入式内核启用,因为它在多用户系统上是不安全的。

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

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

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

区别1:

Malloc()通常分配内存块,它是初始化的内存段。

Calloc()分配内存块并将所有内存块初始化为0。

区别2:

如果考虑malloc()语法,它只需要1个参数。考虑下面的例子:

data_type ptr = (cast_type *)malloc( sizeof(data_type)*no_of_blocks );

例如:如果你想为int类型分配10块内存,

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

如果考虑calloc()语法,它将接受2个参数。考虑下面的例子:

data_type ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));

例如:如果你想为int类型分配10块内存,并将所有这些初始化为0,

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

相似度:

malloc()和calloc()如果没有进行类型强制转换,默认情况下都会返回void* !

摘自Georg Hager的博客上的一篇文章,用calloc()进行有趣的基准测试

When allocating memory using calloc(), the amount of memory requested is not allocated right away. Instead, all pages that belong to the memory block are connected to a single page containing all zeroes by some MMU magic (links below). If such pages are only read (which was true for arrays b, c and d in the original version of the benchmark), the data is provided from the single zero page, which – of course – fits into cache. So much for memory-bound loop kernels. If a page gets written to (no matter how), a fault occurs, the “real” page is mapped and the zero page is copied to memory. This is called copy-on-write, a well-known optimization approach (that I even have taught multiple times in my C++ lectures). After that, the zero-read trick does not work any more for that page and this is why performance was so much lower after inserting the – supposedly redundant – init loop.