What is the difference between doing:
ptr = (char **) malloc (MAXELEMS * sizeof(char *));
// OR
ptr = (char **) calloc (MAXELEMS, sizeof(char*));
???
EDT: When is it a good idea to use calloc over malloc or vice versa?
What is the difference between doing:
ptr = (char **) malloc (MAXELEMS * sizeof(char *));
// OR
ptr = (char **) calloc (MAXELEMS, sizeof(char*));
???
EDT: When is it a good idea to use calloc over malloc or vice versa?
calloc() zero-initializes the buffer, while malloc() leaves the memory uninitialized.
EDIT:
Zeroing out the memory may take a little time, so you probably want to use malloc() if that performance is an issue. If initializing the memory is more important, use calloc(). For example, calloc() might save you a call to memset().
A less known difference is that in operating systems with optimistic memory allocation, like Linux, the pointer returned by malloc
isn't backed by real memory until the program actually touches it.
calloc
does indeed touch the memory (it writes zeroes on it) and thus you'll be sure the OS is backing the allocation with actual RAM (or swap). This is also why it is slower than malloc (not only does it have to zero it, the OS must also find a suitable memory area by possibly swapping out other processes)
See for instance this SO question for further discussion about the behavior of malloc
There's no difference in the size of the memory block allocated. calloc
just fills the memory block with physical all-zero-bits pattern. In practice it is often assumed that the objects located in the memory block allocated with calloc
have initilial value as if they were initialized with literal 0
, i.e. integers should have value of 0
, floating-point variables - value of 0.0
, pointers - the appropriate null-pointer value, and so on.
From the pedantic point of view though, calloc
(as well as memset(..., 0, ...)
) is only guaranteed to properly initialize (with zeroes) objects of type unsigned char
. Everything else is not guaranteed to be properly initialized and may contain so called trap representation, which causes undefined behavior. In other words, for any type other than unsigned char
the aforementioned all-zero-bits patterm might represent an illegal value, trap representation.
Later, in one of the Technical Corrigenda to C99 standard, the behavior was defined for all integer types (which makes sense). I.e. formally, in the current C language you can initialize only integer types with calloc
(and memset(..., 0, ...)
). Using it to initialize anything else in general case leads to undefined behavior, from the point of view of C language.
In practice, calloc
works, as we all know :), but whether you'd want to use it (considering the above) is up to you. I personally prefer to avoid it completely, use malloc
instead and perfrom my own initialization.
One often-overlooked advantage of calloc
is that (conformant implementations of) it will help protect you against integer overflow vulnerabilities. Compare:
size_t cnt = get_int32(file);
struct foo *bar = malloc(cnt * sizeof *bar);
vs.
size_t cnt = get_int32(file);
struct foo *bar = calloc(cnt, sizeof *bar);
The former could result in a tiny allocation and subsequent buffer overflows, if cnt
is greater than SIZE_MAX/sizeof *bar
. The latter will automatically fail in this case since an object that large cannot be created.
Of course you may have to be on the lookout for non-conformant implementations which simply ignore the possibility of overflow... If this is a concern on platforms you target, you'll have to do a manual test for overflow anyway.