提问



做的有什么区别:


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


要么:


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


什么时候使用calloc而不是malloc是一个好主意,反之亦然?

最佳参考


calloc()零初始化缓冲区,而malloc()使内存未初始化。


修改


将内存清零可能需要一些时间,因此如果性能有问题,您可能希望使用malloc()。如果初始化内存更重要,请使用calloc()。例如,calloc()可能会保存您对memset()的调用。

其它参考1


一个鲜为人知的区别是,在具有乐观内存分配的操作系统中,如Linux,malloc返回的指针不受实际内存的支持,直到程序实际触及它为止。


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


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

其它参考2


calloc的一个经常被忽视的优点是(符合实现)它将有助于保护您免受整数溢出漏洞的影响。比较:


size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);





size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);


如果count大于SIZE_MAX/sizeof *bar,前者可能导致微小的分配和随后的缓冲区溢出。在这种情况下,后者将自动失败,因为无法创建大的对象。


当然,您可能需要注意不符合要求的实现,这些实现只是忽略了溢出的可能性......如果这是您所针对的平台上的一个问题,那么无论如何您都必须对溢出进行手动测试。

其它参考3


该文档使calloc看起来像malloc,它只是对内存进行零初始化;这不是主要的区别! calloc的想法是为内存分配禁止写时复制语义。使用calloc分配内存时,它都会映射到初始化为零的同一物理页面。当分配的存储器的任何页面被写入物理页面时被分配。这通常用于制作HUGE哈希表,例如,因为空的哈希部分不会被任何额外的内存(页面)支持;它们很乐意指向单个零初始化页面,甚至可以在进程之间共享。


对虚拟地址的任何写入都映射到页面,如果该页面是零页面,则分配另一个物理页面,在那里复制零页面,并将控制流程返回给客户端进程。这与内存映射文件,虚拟内存等工作方式相同。它使用分页。


以下是关于该主题的一个优化故事:
http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/[105]

其它参考4


分配的内存块大小没有区别。calloc只是用物理全零位模式填充内存块。实际上,通常假设位于内存块中的对象分配了[[calloc具有初始值,好像它们是用文字0初始化的,即整数应该具有0的值,浮点变量 - 0.0的值,指针 - 适当的空值-pointer值,等等。


从迂腐的角度来看,calloc(以及memset(..., 0, ...))只能保证正确初始化(用零)unsigned char类型的对象。其他所有内容都不能保证正确初始化,并且可能包含所谓的陷阱表示,这会导致未定义的行为。换句话说,对于unsigned char之外的任何类型,前面提到的全零比特模式可能代表非法值,即陷阱表示。


后来,在C99标准的技术勘误之一中,为所有整数类型定义了行为(这是有道理的)。即形式上,在当前的C语言中,您只能用calloc(和memset(..., 0, ...))初始化整数类型。从C语言的角度来看,使用它初始化其他任何一般情况都会导致未定义的行为。


在实践中,calloc有效,我们都知道:),但是你是否想要使用它(考虑到上述情况)取决于你。我个人更喜欢完全避免它,使用malloc而是执行我自己的初始化。


最后,另一个重要细节是calloc需要通过将元素大小乘以元素数量来计算内部内部的最终块大小。在这样做时,calloc必须注意可能的算术溢出。如果无法正确计算所请求的块大小,则会导致分配失败(空指针)。同时,您的malloc版本不会尝试监视溢出。如果发生溢出,它将分配一些不可预测的内存量。

其它参考5


来自一篇文章使用calloc()和在Georg Hager的博客上的零页面进行基准测试[106] [107]



??使用calloc()分配内存时,不会立即分配请求的内存量。相反,属于内存块的所有页面都通过某些MMU魔法连接到包含全零的单个页面(下面的链接)。如果仅读取此类页面(对于基准测试的原始版本中的数组b,c和d都是如此),则数据从单个零页面提供,当然,该页面适合缓存。对于内存限制的循环内核来说非常重要。如果页面被写入(无论如何),则发生故障,映射真实页面并将零页面复制到存储器。这称为写时复制,这是一种众所周知的优化方法(我甚至已经在我的C ++讲座中多次教过)。之后,零读取技巧不再适用于该页面,这就是为什么在插入 - 假设冗余的 - init循环后性能如此低的原因。


其它参考6


calloc通常malloc+memset为0


明确地使用malloc+memset通常稍微好一点,特别是当你做的事情时:


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


这是更好的,因为在编译时编译器知道sizeof(Item),并且编译器在大多数情况下会用最好的指令替换它以使内存为零。另一方面,如果在calloc中发生memset,则calloc代码中不会编译分配的参数大小,并且通常会调用实际memset,通常包含用于逐字节填充直到长边界的代码,而不是循环来填充sizeof(long)块中的存储器,最后逐字节填充剩余空间。即使分配器足够聪明,可以调用某些aligned_memset,它仍然是一个通用循环。


一个值得注意的例外是当你正在进行一大块内存(一些power_of_two千字节)的malloc/calloc时,在这种情况下,可以直接从内核完成分配。由于操作系统内核通常会将出于安全原因而放弃的所有内存归零,因此足够聪明的calloc可能会将其返回并进行额外的归零。再说一遍 - 如果你只是分配你知道的东西很小,那么你可能会更好地使用malloc + memset。

其它参考7


malloc()分配给定大小的内存块(以字节为单位)并返回指向块开头的指针。


void *malloc(size_t size);


malloc()不初始化分配的内存。


calloc()分配内存并初始化分配内存到所有位零。


void *calloc(size_t num, size_t size);

其它参考8


差异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块内存并将所有内容初始化为ZERO,


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


相似:


如果malloc()和calloc()没有类型化,它们将默认返回void *。

其它参考9


有两点不同。

首先,是参数的数量。 malloc()只需要一个参数(以字节为单位的内存),而calloc()需要两个参数。点击
其次,malloc()不初始化分配的内存,而calloc()将分配的内存初始化为ZERO。



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



语法:ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block);
ptr_var=(type *)calloc(n,s);



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



语法:ptr_var=(cast_type *)malloc(Size_in_bytes);
malloc()函数接受一个参数,即要分配的字节数,而calloc()函数接受两个参数,一个是元素数,另一个是要分配的字节数每个元素。此外,calloc()将分配的空间初始化为零,而malloc()则不。

其它参考10


标题中声明的calloc()函数比malloc()函数提供了一些优势。



  1. 它将内存分配给给定大小的多个元素,

  2. 初始化分配的内存,以便所有位都是
    零。


其它参考11


尚未提及的差异:大小限制


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字节,代码想要使用 lot 扇区。这里,代码最多只能使用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 GBytes中。[108]

其它参考12


malloc和calloc之间的主要区别是:



  1. malloc代表内存分配,而calloc代表连续分配

  2. malloc只接受一个参数,块的大小,而calloc接受两个参数,要分配的块数和每个块的大小。


    ptr =(cast-type *)malloc(byte-size)//malloc


    ptr =(cast-type *)calloc(没有块,块大小);//calloc

  3. malloc不执行内存初始化,所有地址都存储垃圾值,而calloc执行内存初始化,地址初始化为零或空值


其它参考13


malloc():分配请求的字节大小并返回指定分配空间的第一个字节


calloc():为数组元素分配空间,初始化为零,然后返回指向内存的指针

其它参考14


名称malloc和calloc()是动态分配内存的库函数。
这意味着在堆段的运行时(程序执行)期间分配内存。


初始化:malloc()分配给定大小的内存块(以字节为单位)并返回指向块开头的指针。


>  malloc() doesn’t initialize the allocated memory. If we try to access
 the content of memory block then we’ll get garbage values. void *
> malloc( size_t size );

> calloc() allocates the memory and also initializes the allocates
 memory block to zero. If we try to access the content of these blocks
 then we’ll get 0.

> void * calloc( size_t num, size_t size );



??许多参数:与malloc()不同,calloc()有两个参数:
??1)要分配的块数。 2)每个块的大小。



最重要的 :



??最好在calloc上使用malloc,除非我们想要零初始化,因为malloc比calloc更快。所以,如果我们
??只是想复制一些东西或做一些不需要的东西
??用零填充块,然后malloc会更好
??选择。



其它参考15


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


只需分配n bytes内存而无需任何初始化(即;那些内存字节将包含任何垃圾值)。


char *ptr = (char *) malloc (n, sizeof(char));


但是,除了malloc()所做的函数之外,c中的calloc()方法对所有占用的存储器字节的0值进行初始化。


但除此之外,还有一个非常重要的区别。在调用malloc(x)时,它将分配内存(等于x块)并将指针返回到分配的第一个字节。但是,它不会验证是否分配了x个内存块。这将导致内存溢出的情况。但是calloc()验证分配大小。如果它在分配内存或验证分配的字节方面失败,它将只返回null。

其它参考16


malloc()接受一个参数,而calloc()接受两个参数。


其次,malloc()不初始化分配的内存,而calloc()将分配的内存初始化为ZERO。 malloc和calloc都在C语言中用于动态内存分配,它们动态获取内存块。

其它参考17


malloc()calloc()是C标准库中允许动态内存分配的函数,这意味着它们都允许在运行时分配内存。


他们的原型如下:


void *malloc( size_t n);
void *calloc( size_t n, size_t t)


两者之间主要有两点不同:



  • 行为:malloc()分配一个内存块,而不进行初始化,从该块读取内容将导致垃圾值。 calloc(),另一方面,分配一个内存块并将其初始化为零,显然读取该块的内容将导致零。

  • 语法:malloc()取1个参数(要分配的大小),calloc()取两个参数(要分配的块数和每个块的大小)。



如果成功,则两者的返回值是指向已分配的内存块的指针。否则,将返回 NULL ,表示内存分配失败。


示例:


int *arr;

// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int)); 

// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));


使用malloc()memset()可以实现与calloc()相同的功能:


// allocate memory for 10 integers with garbage values   
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int)); 


请注意,malloc()最好在calloc()上使用,因为它更快。如果需要对值进行零初始化,请改用calloc()