区别是什么:
ptr = malloc(MAXELEMS * sizeof(char *));
And:
ptr = calloc(MAXELEMS, sizeof(char*));
什么时候使用calloc优于malloc或反之亦然?
区别是什么:
ptr = malloc(MAXELEMS * sizeof(char *));
And:
ptr = calloc(MAXELEMS, sizeof(char*));
什么时候使用calloc优于malloc或反之亦然?
当前回答
一个不太为人所知的区别是,在具有乐观内存分配的操作系统(如Linux)中,由malloc返回的指针直到程序实际接触它时才得到实际内存的支持。
calloc确实会接触内存(它会在内存上写0),因此您可以确定操作系统正在用实际的RAM(或swap)支持分配。这也是为什么它比malloc慢的原因(它不仅必须将它归零,操作系统还必须通过交换其他进程来找到合适的内存区域)
例如,请参阅这个SO问题以进一步讨论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,前者可能导致少量分配和后续缓冲区溢出。在这种情况下,后者将自动失败,因为无法创建如此大的对象。
当然,您可能不得不注意不符合规范的实现,这些实现简单地忽略了溢出的可能性……如果在您的目标平台上存在这个问题,那么无论如何都必须对溢出进行手动测试。
分配的内存块大小没有差异。Calloc只是用物理全零位模式填充内存块。在实践中,通常假设位于用calloc分配的内存块中的对象具有初始值,就像它们是用文字0初始化的一样,即整数的值应该是0,浮点变量的值应该是0.0,指针的值应该是适当的空指针值,等等。
然而,从学究的角度来看,calloc(以及memset(…, 0,…))只能保证正确地初始化unsigned char类型的对象(使用0)。其他所有内容都不能保证被正确初始化,并且可能包含所谓的陷阱表示,这会导致未定义的行为。换句话说,对于除unsigned char以外的任何类型,前面提到的全零位模式可能表示非法值,即陷阱表示。
后来,在C99标准的一个技术更正中,为所有整数类型定义了行为(这是有意义的)。也就是说,在当前的C语言中,你只能用calloc(和memset(…, 0,…))。从C语言的角度来看,在一般情况下使用它来初始化其他任何东西都会导致未定义的行为。
在实践中,calloc工作,我们都知道:),但是否想要使用它(考虑到上面的问题)取决于你。我个人更倾向于完全避免它,而是使用malloc并执行自己的初始化。
最后,另一个重要的细节是,calloc需要在内部计算最终的块大小,通过将元素大小乘以元素数量。在执行此操作时,calloc必须监视可能的算术溢出。如果无法正确计算请求的块大小,将导致分配不成功(空指针)。同时,您的malloc版本不会尝试监视溢出。它将分配一些“不可预测”的内存数量,以防发生溢出。
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()。
一个不太为人所知的区别是,在具有乐观内存分配的操作系统(如Linux)中,由malloc返回的指针直到程序实际接触它时才得到实际内存的支持。
calloc确实会接触内存(它会在内存上写0),因此您可以确定操作系统正在用实际的RAM(或swap)支持分配。这也是为什么它比malloc慢的原因(它不仅必须将它归零,操作系统还必须通过交换其他进程来找到合适的内存区域)
例如,请参阅这个SO问题以进一步讨论malloc的行为
在<stdlib.h>标头中声明的calloc()函数比malloc()函数提供了几个优点。
它将内存分配为一定数量的给定大小的元素 它初始化所分配的内存,这样所有的位都是 零。