区别是什么:

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

And:

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

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


当前回答

calloc的一个经常被忽视的优点是,它将帮助保护您免受整数溢出漏洞的侵害。比较:

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

vs.

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

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

当然,您可能不得不注意不符合规范的实现,这些实现简单地忽略了溢出的可能性……如果在您的目标平台上存在这个问题,那么无论如何都必须对溢出进行手动测试。

其他回答

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

他们的原型如下:

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

两者的区别主要有两点:

行为:malloc()分配一个内存块,不初始化它,从这个块中读取内容将导致垃圾值。另一方面,Calloc()分配一个内存块并将其初始化为0,显然读取这个块的内容将导致为0。 语法:malloc()有一个参数(要分配的大小),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()。

区别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* !

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

有两个不同之处。 首先,是参数的数量。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的一个经常被忽视的优点是,它将帮助保护您免受整数溢出漏洞的侵害。比较:

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

vs.

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

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

当然,您可能不得不注意不符合规范的实现,这些实现简单地忽略了溢出的可能性……如果在您的目标平台上存在这个问题,那么无论如何都必须对溢出进行手动测试。