No. It does not. It may, but nothing requires it. Small allocations may be handled by already resident pages. Large allocations are mmap'd and since those pages will be zeroed by the kernel, calloc doesn't need to touch them. None of the callocs in in any of the standard c libraries used by the popular open source unix flavors (I looked at Linux/glibc, FreeBSD, NetBSD, and OpenBSD) will call memset to zero a page which will already be zeroed by the kernel before being made available to the process.
The most obvious explanation for why your system shows no difference between malloc+memset and calloc is that your c library's calloc is naive. Or perhaps your code is flawed. Or perhaps your kernel vm subsystem is prefaulting for some reason. Or perhaps your system's environment has enabled malloc/calloc options which affect their behavior (such as filling the allocation with "junk" or zeroes). Perhaps one of the bazillion linux kernel compile options is to blame. If it were my system, I'd look into it just to satisfy my curiosity.
Obviously. My point is only that under certain conditions malloc and calloc are practically identical (both will return zeroed memory without calling memset). See for yourself in the malloc.c source links I provided in an earlier post. You'll find that both are implemented using the same internal routines. Further, if you follow the code path for a large allocation, you'll see that a calloc never memsets (unless certain options which are disabled by default are enabled).
I must retract my earlier quarter of a second figure. I cannot reproduce it. I must have misread the value. Perhaps it was 2.50s instead of 0.25s.
Here's some code and timings from OS X running on a 2.16 GHz Core2Duo Macbook with 2 GB of 667 MHz DDR2 (similar results were observed using NetBSD on similar hardware). Without any command line arguments, the executable will attempt to calloc 1 GiB. With command line arguments, it will malloc and memset 1 GiB:
$ cat large-calloc.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ALLOCSIZE 1073741824U
int
main (int argc, char **argv) {
void *vp;
if (argc == 1) {
if ((vp = calloc(1, ALLOCSIZE)) == NULL)
return 1;
}
else {
if ((vp = malloc(ALLOCSIZE)) == NULL)
return 1;
memset(vp, 0, ALLOCSIZE);
}
printf("%p\n", vp);
return 0;
}
$ cc -Wall -pedantic large-calloc.c
$ time ./a.out
0x2008000
real 0m0.005s # calloc
user 0m0.001s
sys 0m0.004s
$ time ./a.out with-memset
0x2008000
real 0m2.124s # malloc + memset
user 0m0.946s
sys 0m1.168s
That's your prerogative, but, for a large allocation with a reasonably recent C library, you're choosing to use memset to zero malloc'd memory that is probably already zeroed, instead of using calloc, which knows whether the memory is already zeroed and can avoid the overhead of a redundant memset.
So long as they're not aimed at my code, use your guns as you see fit.
Regards,
Alister